See depreecated/README for details.
garmin_device_xml.o garmin_tables.o internal_styles.o nmea.o kml.o \
wbt-200.o ozi.o pcx.o gdb.o gtrnctr.o xcsv.o explorist_ini.o
-ALL_FMTS=$(MINIMAL_FMTS) gtm.o gpsutil.o cetus.o copilot.o \
- gpspilot.o magnav.o skytraq.o \
- psp.o holux.o tmpro.o tpg.o tpo.o \
- gcdb.o tiger.o easygps.o quovadis.o \
- gpilots.o saroute.o navicache.o psitrex.o geoniche.o delgpl.o \
- text.o html.o palmdoc.o netstumbler.o hsa_ndv.o \
- igc.o brauniger_iq.o shape.o hiketech.o glogbook.o coastexp.o \
+ALL_FMTS=$(MINIMAL_FMTS) gtm.o gpsutil.o \
+ skytraq.o \
+ holux.o tmpro.o tpg.o tpo.o \
+ tiger.o easygps.o \
+ saroute.o navicache.o psitrex.o delgpl.o \
+ text.o html.o netstumbler.o \
+ igc.o brauniger_iq.o shape.o hiketech.o glogbook.o \
vcf.o overlay.o google.o xhtmlent.o lowranceusr.o an1.o tomtom.o \
- tef_xml.o maggeo.o pathaway.o vitosmt.o bcr.o coto.o \
- ignrando.o stmwpp.o msroute.o cst.o nmn4.o mag_pdb.o compegps.o \
+ tef_xml.o maggeo.o vitosmt.o bcr.o \
+ ignrando.o stmwpp.o cst.o nmn4.o compegps.o \
yahoo.o unicsv.o wfff_xml.o garmin_txt.o axim_gpb.o gpssim.o \
stmsdf.o dmtlog.o raymarine.o alan.o vitovtt.o \
ggv_log.o g7towin.o garmin_gpi.o lmx.o random.o xol.o dg-100.o \
# Extra modules in Jeeps that we don't use
# jeeps/gpsfmt.o jeeps/gpsinput.o jeeps/gpsproj.o
-
-@PALM_DB_CMT@PALM_DB=pdbfile.o
-
SHAPE=shapelib/shpopen.o shapelib/dbfopen.o
ZLIB=zlib/adler32.o zlib/compress.o zlib/crc32.o zlib/deflate.o zlib/inffast.o \
cet/iso_8859_13.h cet/iso_8859_14.h cet/iso_8859_3.h cet/iso_8859_4.h \
cet/iso_8859_5.h cet/iso_8859_6.h cet/iso_8859_7.h cet/iso_8859_9.h \
cet/koi8_r.h cet/koi8_ru.h cet/koi_8.h
-cetus.o: cetus.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
- gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h \
- pdbfile.h
-coastexp.o: coastexp.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
- gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h \
- xmlgeneric.h uuid.h
compegps.o: compegps.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h \
csv_util.h jeeps/gpsmath.h jeeps/gps.h jeeps/gpsport.h \
jeeps/gpsdevice.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \
jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \
jeeps/gpsmem.h jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h
-copilot.o: copilot.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
- gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h \
- pdbfile.h grtcirc.h
-coto.o: coto.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h gbfile.h \
- cet.h cet_util.h inifile.h session.h src/core/datetime.h csv_util.h \
- pdbfile.h grtcirc.h
cst.o: cst.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h gbfile.h \
cet.h cet_util.h inifile.h session.h src/core/datetime.h strptime.h
csv_util.o: csv_util.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
zlib/zconf.h gbfile.h cet.h cet_util.h inifile.h session.h \
src/core/datetime.h gbser.h gbser_private.h
gbsleep.o: gbsleep.cc config.h
-gcdb.o: gcdb.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h gbfile.h \
- cet.h cet_util.h inifile.h session.h src/core/datetime.h pdbfile.h
gdb.o: gdb.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h gbfile.h \
cet.h cet_util.h inifile.h session.h src/core/datetime.h csv_util.h \
garmin_fs.h jeeps/gps.h jeeps/gpsport.h jeeps/gpsdevice.h \
garmin_tables.h grtcirc.h
geo.o: geo.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h gbfile.h \
cet.h cet_util.h inifile.h session.h src/core/datetime.h src/core/file.h
-geoniche.o: geoniche.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
- gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h \
- pdbfile.h jeeps/gpsmath.h jeeps/gps.h jeeps/gpsport.h \
- jeeps/gpsdevice.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \
- jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \
- jeeps/gpsmem.h jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h \
- garmin_tables.h
ggv_log.o: ggv_log.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h \
grtcirc.h jeeps/gpsmath.h jeeps/gps.h jeeps/gpsport.h \
jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \
jeeps/gpsmem.h jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h \
grtcirc.h
-gpilots.o: gpilots.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
- gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h \
- pdbfile.h garmin_tables.h
-gpspilot.o: gpspilot.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
- gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h \
- pdbfile.h
gpssim.o: gpssim.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h
gpsutil.o: gpsutil.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
holux.o: holux.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h \
holux.h
-hsa_ndv.o: hsa_ndv.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
- gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h
html.o: html.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h gbfile.h \
cet.h cet_util.h inifile.h session.h src/core/datetime.h \
jeeps/gpsmath.h jeeps/gps.h jeeps/gpsport.h jeeps/gpsdevice.h \
mac/libusb/error.h
mac/libusb/usb.o: mac/libusb/usb.c mac/libusb/usbi.h mac/libusb/usb.h \
mac/libusb/error.h
-mag_pdb.o: mag_pdb.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
- gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h \
- pdbfile.h jeeps/gpsmath.h jeeps/gps.h jeeps/gpsport.h \
- jeeps/gpsdevice.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \
- jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \
- jeeps/gpsmem.h jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h
maggeo.o: maggeo.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h \
csv_util.h xmlgeneric.h magellan.h
-magnav.o: magnav.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
- gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h \
- pdbfile.h
magproto.o: magproto.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h \
magellan.h gbser.h explorist_ini.h
gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h
mmo.o: mmo.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h gbfile.h \
cet.h cet_util.h inifile.h session.h src/core/datetime.h
-msroute.o: msroute.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
- gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h \
- jeeps/gpsmath.h jeeps/gps.h jeeps/gpsport.h jeeps/gpsdevice.h \
- jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h jeeps/gpsapp.h \
- jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h jeeps/gpsmem.h \
- jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h
mtk_locus.o: mtk_locus.cc defs.h config.h queue.h zlib/zlib.h \
zlib/zconf.h gbfile.h cet.h cet_util.h inifile.h session.h \
src/core/datetime.h gbser.h
jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h jeeps/gpsapp.h \
jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h jeeps/gpsmem.h \
jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h
-palmdoc.o: palmdoc.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
- gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h \
- jeeps/gpsmath.h jeeps/gps.h jeeps/gpsport.h jeeps/gpsdevice.h \
- jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h jeeps/gpsapp.h \
- jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h jeeps/gpsmem.h \
- jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h pdbfile.h
parse.o: parse.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h \
jeeps/gpsmath.h jeeps/gps.h jeeps/gpsport.h jeeps/gpsdevice.h \
jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h jeeps/gpsapp.h \
jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h jeeps/gpsmem.h \
jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h strptime.h
-pathaway.o: pathaway.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
- gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h \
- csv_util.h pdbfile.h strptime.h
pcx.o: pcx.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h gbfile.h \
cet.h cet_util.h inifile.h session.h src/core/datetime.h \
garmin_tables.h csv_util.h
-pdbfile.o: pdbfile.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
- gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h \
- pdbfile.h
pocketfms_bc.o: pocketfms_bc.cc defs.h config.h queue.h zlib/zlib.h \
zlib/zconf.h gbfile.h cet.h cet_util.h inifile.h session.h \
src/core/datetime.h
psitrex.o: psitrex.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h \
garmin_tables.h
-psp.o: psp.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h gbfile.h \
- cet.h cet_util.h inifile.h session.h src/core/datetime.h grtcirc.h
queue.o: queue.cc queue.h
-quovadis.o: quovadis.cc quovadis.h defs.h config.h queue.h zlib/zlib.h \
- zlib/zconf.h gbfile.h cet.h cet_util.h inifile.h session.h \
- src/core/datetime.h pdbfile.h
radius.o: radius.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
gbfile.h cet.h cet_util.h inifile.h session.h src/core/datetime.h \
filterdefs.h grtcirc.h
+++ /dev/null
-/*
- Read and write Cetus files.
-
- Copyright (C) 2002-2008 Robert Lipe, robertlipe@usa.net
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
-
- */
-
-/*
-
- History:
-
- 2005/08/03: Added track_read by O.K.
- (Thanx to Adam Schneider for additional information)
-
-*/
-
-#include "defs.h"
-#if PDBFMTS_ENABLED
-#include "pdbfile.h"
-
-#define MYNAME "Cetus"
-#define MYTYPE_WPT 0x43577074 /* CWpt */
-#define MYTYPE_TRK 0x7374726d /* strm */
-
-#define MYCREATOR 0x63475053 /* cGPS */
-#define MYTRACK 0x44424c4b /* DBLK */
-
-#define NOTESZ 4096
-#define DESCSZ 4096
-
-typedef enum {
- WptEdit = 0, /* the position has been edited or it was */
- /* imported from another source */
- WptGPS2D = 1, /* retrieved from a GPS with a 2D fix */
- WptGPS3D = 2, /* retrieved from a GPS with a 3D fix */
- WptDGPS2D = 3, /* retrieved from a GPS with a 2D fix and DGPS signal */
- WptDGPS3D = 4, /* retrieved from a GPS with a 3D fix and DGPS signal */
- WptAverage = 5, /* averaging over 3D positions */
- WptCache = 50, /* this position is a geocache reference */
- WptGarmin = 70 /* this position was imported from a Garmin GPS */
- /* the icon field contains the garmin symbol number */
-} wpt_type;
-
-struct cetus_wpt_s {
- char type;
-
- char readonly;
-
- pdb_32 latitude; /* Big endian, degrees*1e7, s=negative */
- pdb_32 longitude; /* same as lat; w=negative */
- pdb_32 elevation; /* Big endian, meters*100. blank=-1e8 */
-
- pdb_16 year; /* sample time, UTC */
- unsigned char mon;
- unsigned char day;
- unsigned char hour;
- unsigned char min;
- unsigned char sec;
-
- /* accuracy and precision information for use where applicable */
- unsigned char sat; /* ff if averaged or unknown */
- pdb_16 pdop; /* pdop * 100 */
- pdb_16 hdop;
- pdb_16 vdop;
- pdb_16 dgpstime;
- pdb_32 dgpsstn;
- pdb_32 avgtime;
- pdb_32 avgite;
-
- pdb_16 dopmask;
- pdb_16 elevmask;
-
- pdb_16 radius;
- pdb_32 distance;
-
- pdb_16 vyear; /* date visited */
- unsigned char vmon;
- unsigned char vday;
- unsigned char vhour;
- unsigned char vmin;
- unsigned char vsec;
-
- char flagged;
-
- pdb_32 icon;
- pdb_16 category;
-};
-
-typedef struct cetus_track_head_s {
- char id[2];
- char version;
- unsigned char interval;
- unsigned short gps;
- char year;
- char month;
- char day;
- char hour;
- char min;
- char sec;
- char dsec;
- char tz;
- char desc;
-} cetus_track_head_t;
-
-#define TRACK_HEAD_SIZE sizeof(struct cetus_track_head_s)
-
-typedef struct cetus_track_point_s {
- signed char hour;
- signed char min;
- signed char sec;
- signed char dsec;
- signed char sat;
- signed char hdop;
- pdb_32 latitude;
- pdb_32 longitude;
- short speed;
- short course;
- pdb_32 elevation;
-} cetus_track_point_t;
-
-#define TRACK_POINT_SIZE sizeof(struct cetus_track_point_s)
-
-static pdbfile* file_in, *file_out;
-static const char* out_fname;
-static short_handle mkshort_wr_handle;
-static int ct;
-
-static char* dbname = NULL;
-static char* appendicon = NULL;
-
-static
-arglist_t cetus_args[] = {
- {
- "dbname", &dbname, "Database name", NULL, ARGTYPE_STRING,
- ARG_NOMINMAX
- },
- {
- "appendicon", &appendicon, "Append icon_descr to description",
- NULL, ARGTYPE_BOOL, ARG_NOMINMAX
- },
- ARG_TERMINATOR
-};
-
-static waypoint*
-read_track_point(cetus_track_point_t* data, const time_t basetime)
-{
- int i, ilat, ilon;
- waypoint* wpt;
-
- ilat = be_read32(&data->latitude);
- ilon = be_read32(&data->longitude);
-
- if (data->hour == -1 || data->min == -1 || data->sec == -1 ||
- ilat == 2000000000 || ilon == 2000000000) {
- return NULL; /* At least one of basic data is not available */
- }
-
- wpt = waypt_new();
-
- wpt->latitude = (double)ilat / 10000000.0;
- wpt->longitude = (double)ilon / 10000000.0;
-
- i = be_read32(&data->elevation);
- wpt->altitude = (i == -100000000) ? unknown_alt : (double) i / 100.0;
-
- if (data->sat != -1) {
- wpt->sat = data->sat;
- }
- if (data->hdop != -1) {
- wpt->hdop = (float) data->hdop / 10;
- }
-
- i = be_read16(&data->speed);
- if (i != 10000) {
- WAYPT_SET(wpt, speed, KNOTS_TO_MPS((double) i / 10.0)); /* meters/second */
- }
- i = be_read16(&data->course);
- if (i != 4000) {
- WAYPT_SET(wpt, course, (float) i / 10);
- }
-
- switch (data->hour >> 5) { /* extract fix */
- case 1:
- wpt->fix = fix_none;
- break;
- case 2:
- wpt->fix = fix_2d;
- break;
- case 3:
- wpt->fix = fix_3d;
- break;
- case 4:
- wpt->fix = fix_dgps;
- break;
- default:
- break; /* no GPS */
- }
-
- wpt->SetCreationTime(basetime +
- ((data->hour & 0x1F) * 3600) + (data->min * 60) + data->sec, data->dsec * 10);
-
- return wpt;
-}
-
-
-static void
-read_tracks(const pdbfile* pdb)
-{
- pdbrec_t* pdb_rec;
- int reclen, records, total, points, dropped;
- char descr[(2 * TRACK_POINT_SIZE) + 1];
- char temp_descr[TRACK_POINT_SIZE + 1];
- cetus_track_head_t* head;
- waypoint* wpt;
- route_head* track;
- time_t basetime;
-
- track = route_head_alloc();
- track_add_head(track);
-
- total = 0;
- points = 0;
- dropped = 0;
- basetime = 0;
-
- for (pdb_rec = pdb->rec_list; pdb_rec; pdb_rec = pdb_rec->next) {
- int i, magic;
- char* c = (char*)pdb_rec->data;
-
- magic = be_read32(c);
- if (magic != MYTRACK) {
- fatal(MYNAME ": Invaid track data or unsupported version!\n");
- }
-
- reclen = be_read32(c+4);
- records = reclen / TRACK_POINT_SIZE;
-
- c += 8;
-
- for (i = 0; i < records; i++, c += TRACK_POINT_SIZE) {
- switch (total++) {
- struct tm tm;
-
- case 0: /* track header */
- head = (cetus_track_head_t*)c;
- if (head->id[0] != 'C' || head->id[1] != 'G') {
- fatal(MYNAME ": Invalid track header!\n");
- }
-
- memset(&tm, 0, sizeof(tm));
- tm.tm_mday = head->day;
- tm.tm_mon = head->month - 1;
- tm.tm_year = head->year + 100;
- basetime = mkgmtime(&tm);
- break;
-
- case 1: /* first part of description */
- strncpy(descr, c, TRACK_POINT_SIZE);
- break;
-
- case 2: /* continued description */
- strncpy(temp_descr, c, TRACK_POINT_SIZE);
- strcat(descr, temp_descr); /* here is no need to check target size */
- if (strlen(descr) > 0) {
- track->rte_desc = xstrdup(descr);
- }
- break;
-
- default:
- wpt = read_track_point((cetus_track_point_t*)c, basetime);
- if (wpt != NULL) {
- track_add_wpt(track, wpt);
- points++;
- } else {
- dropped++;
- }
- }
-
- }
- }
-
- if (global_opts.verbose_status > 0) {
- printf(MYNAME ": Loaded %d track point(s) from source.\n", points);
- if (dropped > 0) {
- printf(MYNAME ": ! %d dropped because of missing data (no time, no coordinates) !\n", dropped);
- }
- }
-}
-
-static void
-read_waypts(const pdbfile* pdb)
-{
- struct cetus_wpt_s* rec;
- pdbrec_t* pdb_rec;
- char* vdata;
-
- for (pdb_rec = pdb->rec_list; pdb_rec; pdb_rec = pdb_rec->next) {
- waypoint* wpt_tmp;
- int i;
-
- wpt_tmp = waypt_new();
-
- rec = (struct cetus_wpt_s*) pdb_rec->data;
- if (be_read32(&rec->elevation) == -100000000) {
- wpt_tmp->altitude = unknown_alt;
- } else {
- wpt_tmp->altitude = be_read32(&rec->elevation) / 100.0;
- }
-
- wpt_tmp->latitude = be_read32(&rec->latitude) / 10000000.0;
- wpt_tmp->longitude = be_read32(&rec->longitude) / 10000000.0;
-
- if (rec->sat != 0xff) {
- wpt_tmp->sat = rec->sat;
- }
-
- i = be_read16(&rec->pdop);
- if (i != 0xffff) {
- wpt_tmp->pdop = i / 100.0;
- }
- i = be_read16(&rec->hdop);
- if (i != 0xffff) {
- wpt_tmp->hdop = i / 100.0;
- }
- i = be_read16(&rec->vdop);
- if (i != 0xffff) {
- wpt_tmp->vdop = i / 100.0;
- }
-
- switch (rec->type) {
- case WptGPS2D:
- wpt_tmp->fix = fix_2d;
- break;
- case WptGPS3D:
- wpt_tmp->fix = fix_3d;
- break;
- case WptDGPS2D:
- wpt_tmp->fix = fix_dgps;
- break;
- case WptDGPS3D:
- wpt_tmp->fix = fix_dgps;
- break;
- }
-
- if (be_read16(&rec->year) != 0xff) {
- struct tm tm;
-
- memset(&tm, 0, sizeof(tm));
- tm.tm_min = rec->min;
- tm.tm_hour = rec->hour;
- tm.tm_mday = rec->day;
- tm.tm_mon = rec->mon - 1;
- tm.tm_year = be_read16(&rec->year) - 1900;
-
- wpt_tmp->SetCreationTime(mkgmtime(&tm));
-
- }
-
- vdata = (char*) pdb_rec->data + sizeof(*rec);
-
- wpt_tmp->shortname = xstrdup(vdata);
- vdata = vdata + strlen(vdata) + 1;
-
- wpt_tmp->description = xstrdup(vdata);
- vdata = vdata + strlen(vdata) + 1;
-
- wpt_tmp->notes = xstrdup(vdata);
-
- waypt_add(wpt_tmp);
-
- }
-}
-
-/* --------------------------------------------------------------------------- */
-
-static void
-rd_init(const char* fname)
-{
- file_in = pdb_open(fname, MYNAME);
-}
-
-static void
-rd_deinit(void)
-{
- pdb_close(file_in);
- if (dbname) {
- xfree(dbname);
- dbname = NULL;
- }
-}
-
-static void
-wr_init(const char* fname)
-{
- file_out = pdb_create(fname, MYNAME);
- out_fname = fname;
- ct = 0;
-}
-
-static void
-wr_deinit(void)
-{
- pdb_close(file_out);
- if (dbname) {
- xfree(dbname);
- dbname = NULL;
- }
-}
-
-static void
-data_read(void)
-{
- if (file_in->creator != MYCREATOR) {
- fatal(MYNAME ": Not a Cetus file.\n");
- }
-
- switch (file_in->type) {
- case MYTYPE_TRK:
- read_tracks(file_in);
- break;
-
- case MYTYPE_WPT:
- read_waypts(file_in);
- break;
- }
-}
-
-
-static void
-cetus_writewpt(const waypoint* wpt)
-{
- struct cetus_wpt_s* rec;
- char* vdata;
- char* desc_long;
- char* desc_short;
- char* desc_geo;
- char* desc;
-
- rec = (struct cetus_wpt_s*) xcalloc(sizeof(*rec)+18 + NOTESZ + DESCSZ,1);
-
- QDate date(wpt->GetCreationTime().date());
- rec->day = date.day();
- rec->mon = date.month();
- be_write16(&rec->year, date.year());
-
- QTime time(wpt->GetCreationTime().time());
- rec->min = time.minute();
- rec->hour = time.hour();
- rec->sec = time.second();
-
- be_write32(&rec->longitude, (unsigned int)(int)(wpt->longitude * 10000000.0));
- be_write32(&rec->latitude, (unsigned int)(wpt->latitude * 10000000.0));
- if (wpt->altitude == unknown_alt) {
- be_write32(&rec->elevation, -100000000);
- } else {
- be_write32(&rec->elevation, (unsigned int)(wpt->altitude * 100.0));
- }
-
- be_write16(&rec->pdop, wpt->pdop ? wpt->pdop * 100 : 0xffff);
- be_write16(&rec->hdop, wpt->hdop ? wpt->hdop * 100 : 0xffff);
- be_write16(&rec->vdop, wpt->vdop ? wpt->vdop * 100 : 0xffff);
- be_write16(&rec->dgpstime, 0xffff);
- be_write32(&rec->distance, 0xffffffff);
-
- rec->vmin = 0xff;
- rec->vhour = 0xff;
- rec->vsec = 0xff;
- rec->vday = 0xff;
- rec->vmon = 0xff;
- be_write16(&rec->vyear, 0xff);
-
- rec->sat = wpt->sat ? wpt->sat : 0xff;
-
- vdata = (char*)rec + sizeof(*rec);
- if (wpt->shortname) {
- char* sn = xstrdup(wpt->shortname);
- strncpy(vdata, sn, 16);
- vdata[15] = '\0';
- xfree(sn);
- } else {
- vdata[0] ='\0';
- }
- vdata += strlen(vdata) + 1;
-
- if (wpt->gc_data->diff) {
- xasprintf(&desc_geo, "%s%s by %s\n%.4s/%.4s %3.1f/%3.1f\n",
- wpt->gc_data->is_available==status_true ?
- "" : " (Disabled)",
- wpt->gc_data->is_archived==status_true ?
- " (Archived)" : "",
- wpt->gc_data->placer.toUtf8().data(),
- gs_get_cachetype(wpt->gc_data->type),
- gs_get_container(wpt->gc_data->container),
- wpt->gc_data->diff/10.0,
- wpt->gc_data->terr/10.0);
- } else {
- desc_geo = xstrdup("");
- }
-
- if (!wpt->gc_data->desc_short.utfstring.isEmpty()) {
- char* stripped_html = strip_html(&wpt->gc_data->desc_short);
- desc_short = xstrdup(wpt->gc_data->diff == 0 ? "\n\n" : "");
- desc_short = xstrappend(desc_short, xstrdup(stripped_html));
- xfree(stripped_html);
- } else {
- desc_short = xstrdup("");
- }
-
- if (!wpt->gc_data->desc_long.utfstring.isEmpty()) {
- char* stripped_html = strip_html(&wpt->gc_data->desc_long);
- desc_long = xstrdup("\n\n");
- desc_long = xstrappend(desc_long, xstrdup(stripped_html));
- xfree(stripped_html);
- } else {
- desc_long = xstrdup("");
- }
-
- desc = wpt->description ? xstrdup(wpt->description) :
- xstrdup("");
-
- snprintf(vdata, DESCSZ, "%s%s%s%s",
- desc,
- desc_geo,
- desc_short,
- desc_long);
-
- xfree(desc);
- xfree(desc_geo);
- xfree(desc_short);
- xfree(desc_long);
-
- if (appendicon && !wpt->icon_descr.isNull()) {
- int left = DESCSZ - strlen(vdata);
- int ilen = strlen(wpt->icon_descr.toUtf8().data());
- if (ilen && left > (ilen+3)) {
- strcat(vdata, " (");
- strcat(vdata, wpt->icon_descr.toUtf8().data());
- strcat(vdata, ")");
- }
- }
- vdata += strlen(vdata) + 1;
-
- if (!wpt->gc_data->hint.isEmpty()) {
- char* hint = xstrdup(wpt->gc_data->hint.toUtf8().data());
- rec->type = WptCache;
- strncpy(vdata, hint, NOTESZ + 1) ;
- xfree(hint);
- vdata[NOTESZ] = '\0';
- } else {
- rec->type = WptEdit;
- vdata[0] ='\0';
- }
- vdata += strlen(vdata) + 1;
-
- pdb_write_rec(file_out, 0, 2, ct++, rec, (char*)vdata - (char*)rec);
-
- xfree(rec);
-}
-
-struct hdr {
- char* wpt_name;
- waypoint* wpt;
-};
-
-static
-int
-compare(const void* a, const void* b)
-{
- const struct hdr* wa = (const struct hdr*) a;
- const struct hdr* wb = (const struct hdr*) b;
-
- return strcmp(wa->wpt->shortname, wb->wpt->shortname);
-}
-
-static void
-data_write(void)
-{
- int i, ct = waypt_count();
- struct hdr* htable, *bh;
- queue* elem, *tmp;
- extern queue waypt_head;
- waypoint* waypointp;
- mkshort_wr_handle = mkshort_new_handle();
- setshort_length(mkshort_wr_handle, 15);
- setshort_whitespace_ok(mkshort_wr_handle, 0);
-
- if (dbname) {
- strncpy(file_out->name, dbname, PDB_DBNAMELEN);
- } else {
- strncpy(file_out->name, out_fname, PDB_DBNAMELEN);
- }
- file_out->name[PDB_DBNAMELEN-1] = 0;
- file_out->attr = PDB_FLAG_BACKUP;
- file_out->ctime = file_out->mtime = current_time().toTime_t() + 2082844800U;
- file_out->type = MYTYPE_WPT; /* CWpt */
- file_out->creator = MYCREATOR; /* cGPS */
- file_out->version = 1;
-
- /*
- * All this is to sort by waypoint names before going to Cetus.
- * Turns out plain old strcmp will do the trick...
- */
-
- htable = (struct hdr*) xmalloc(ct * sizeof(*htable));
- bh = htable;
-
- QUEUE_FOR_EACH(&waypt_head, elem, tmp) {
- waypointp = (waypoint*) elem;
- bh->wpt = waypointp;
- if (global_opts.synthesize_shortnames && waypointp->description) {
- if (waypointp->shortname) {
- xfree(waypointp->shortname);
- }
- waypointp->shortname = mkshort_from_wpt(mkshort_wr_handle, waypointp);
- }
- bh->wpt_name = waypointp->shortname;
- bh ++;
- }
- qsort(htable, ct, sizeof(*bh), compare);
-
- for (i=0; i<ct; i++) {
- cetus_writewpt(htable[i].wpt);
- }
-
- xfree(htable);
- mkshort_del_handle(&mkshort_wr_handle);
-}
-
-
-ff_vecs_t cetus_vecs = {
- ff_type_file,
- { (ff_cap)(ff_cap_write | ff_cap_read), ff_cap_read, ff_cap_none },
- rd_init,
- wr_init,
- rd_deinit,
- wr_deinit,
- data_read,
- data_write,
- NULL,
- cetus_args,
- CET_CHARSET_MS_ANSI, 0 /* CET-REVIEW */
-};
-#endif
+++ /dev/null
-/*
- Read and write CoPilot files.
-
- Copyright (C) 2002 Paul Tomblin, ptomblin@xcski.com
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
-
- */
-
-#include "defs.h"
-#if PDBFMTS_ENABLED
-#include "pdbfile.h"
-#include "grtcirc.h"
-
-#define MYNAME "CoPilot Waypoint"
-#define wayp_TYPE 0x77617970 /* wayp */
-#define wayu_TYPE 0x77617975 /* wayu */
-#define swpu_TYPE 0x73777075 /* swpu */
-#define GXPU_CREATOR 0x47584255 /* GXBU */
-#define AP_P_CREATOR 0x41502d50 /* AP-P */
-
-
-struct record0 {
- pdb_double latitude; /* PDB double format, */
- pdb_double longitude; /* similarly, neg = east */
- pdb_double magvar; /* magnetic variation in degrees, neg = east */
- uint32_t elevation; /* feet */
-};
-
-struct record1 {
- pdb_double latitude; /* PDB double format, */
- pdb_double longitude; /* similarly, neg = east */
- pdb_double magvar; /* magnetic variation in degrees, neg = east */
- pdb_double elevation; /* feet */
-};
-
-struct record3 {
- pdb_double latitude; /* PDB double format, */
- pdb_double longitude; /* similarly, neg = east */
- pdb_double magvar; /* magnetic variation in degrees, neg = east */
- pdb_double elevation; /* feet */
- char flags; /* flags */
-};
-
-struct record4 {
- pdb_double latitude; /* PDB double format, */
- pdb_double longitude; /* similarly, neg = east */
- pdb_float magvar; /* magnetic variation in degrees, neg = east */
- pdb_float elevation; /* feet */
-};
-
-static pdbfile* file_in, *file_out;
-static const char* out_fname;
-static int ct;
-
-static void
-rd_init(const char* fname)
-{
- file_in = pdb_open(fname, MYNAME);
-}
-
-static void
-rd_deinit(void)
-{
- pdb_close(file_in);
-}
-
-static void
-wr_init(const char* fname)
-{
- file_out = pdb_create(fname, MYNAME);
- out_fname = fname;
- ct = 0;
-}
-
-static void
-wr_deinit(void)
-{
- pdb_close(file_out);
-}
-
-static waypoint*
-read_version0(void* data)
-{
- char* vdata;
- waypoint* wpt_tmp;
- struct record0* rec = (struct record0*)data;
-
- wpt_tmp = waypt_new();
-
- wpt_tmp->longitude =
- DEG(-pdb_read_double(&rec->longitude));
- wpt_tmp->latitude =
- DEG(pdb_read_double(&rec->latitude));
- wpt_tmp->altitude = FEET_TO_METERS(be_read32(&rec->elevation));
-
- vdata = (char*) data + sizeof(*rec);
-
- wpt_tmp->shortname = xstrdup(vdata);
- vdata = vdata + strlen(vdata) + 1;
-
- wpt_tmp->description = xstrdup(vdata);
- vdata = vdata + strlen(vdata) + 1;
-
- wpt_tmp->notes = NULL;
-
- return wpt_tmp;
-}
-
-static waypoint*
-read_version1(void* data)
-{
- char* vdata;
- waypoint* wpt_tmp;
- struct record1* rec = (struct record1*)data;
-
- wpt_tmp = waypt_new();
-
- wpt_tmp->longitude =
- DEG(-pdb_read_double(&rec->longitude));
- wpt_tmp->latitude =
- DEG(pdb_read_double(&rec->latitude));
- wpt_tmp->altitude =
- FEET_TO_METERS(pdb_read_double(&rec->elevation));
-
- vdata = (char*) data + sizeof(*rec);
-
- wpt_tmp->shortname = xstrdup(vdata);
- vdata = vdata + strlen(vdata) + 1;
-
- wpt_tmp->description = xstrdup(vdata);
- vdata = vdata + strlen(vdata) + 1;
-
- wpt_tmp->notes = xstrdup(vdata);
-
- return wpt_tmp;
-}
-
-static waypoint*
-read_version3(void* data)
-{
- char* vdata;
- waypoint* wpt_tmp;
- struct record3* rec = (struct record3*)data;
-
- wpt_tmp = waypt_new();
-
- wpt_tmp->longitude =
- DEG(-pdb_read_double(&rec->longitude));
- wpt_tmp->latitude =
- DEG(pdb_read_double(&rec->latitude));
- wpt_tmp->altitude =
- FEET_TO_METERS(pdb_read_double(&rec->elevation));
-
- vdata = (char*) data + sizeof(*rec);
-
- wpt_tmp->shortname = xstrdup(vdata);
- vdata = vdata + strlen(vdata) + 1;
-
- wpt_tmp->description = xstrdup(vdata);
- vdata = vdata + strlen(vdata) + 1;
-
- wpt_tmp->notes = xstrdup(vdata);
-
- return wpt_tmp;
-}
-
-static waypoint*
-read_version4(void* data)
-{
- char* vdata;
- waypoint* wpt_tmp;
- struct record4* rec = (struct record4*)data;
-
- wpt_tmp = waypt_new();
-
- wpt_tmp->longitude =
- DEG(-pdb_read_double(&rec->longitude));
- wpt_tmp->latitude =
- DEG(pdb_read_double(&rec->latitude));
- wpt_tmp->altitude =
- FEET_TO_METERS(pdb_read_float(&rec->elevation));
-
- vdata = (char*) data + sizeof(*rec);
-
- wpt_tmp->shortname = xstrdup(vdata);
- vdata = vdata + strlen(vdata) + 1;
-
- wpt_tmp->description = xstrdup(vdata);
- vdata = vdata + strlen(vdata) + 1;
-
- wpt_tmp->notes = xstrdup(vdata);
-
- return wpt_tmp;
-}
-
-static void
-data_read(void)
-{
- pdbrec_t* pdb_rec;
-
- if ((file_in->creator != GXPU_CREATOR && file_in->creator != AP_P_CREATOR) ||
- (file_in->type != wayp_TYPE && file_in->type != swpu_TYPE &&
- file_in->type != wayu_TYPE)) {
- fatal(MYNAME ": Not a CoPilot file.\n");
- }
- if (file_in->version > 4) {
- fatal(MYNAME ": %d is not a known version.\n", file_in->version);
- }
-
-
- for (pdb_rec = file_in->rec_list; pdb_rec; pdb_rec = pdb_rec->next) {
- waypoint* wpt_tmp;
-
- switch (file_in->version) {
- case 0:
- wpt_tmp = read_version0(pdb_rec->data);
- break;
- case 1:
- case 2:
- wpt_tmp = read_version1(pdb_rec->data);
- break;
- case 3:
- wpt_tmp = read_version3(pdb_rec->data);
- break;
- case 4:
- wpt_tmp = read_version4(pdb_rec->data);
- break;
- default:
- fatal(MYNAME ": Unknown version %d.\n", file_in->version);
- }
- waypt_add(wpt_tmp);
- }
-}
-
-static void
-copilot_writewpt(const waypoint* wpt)
-{
- struct record4* rec;
- char* vdata;
-
- rec = (struct record4*) xcalloc(sizeof(*rec)+1141,1);
-
- pdb_write_double(&rec->latitude, RAD(wpt->latitude));
- pdb_write_double(&rec->longitude, RAD(-wpt->longitude));
- pdb_write_float(&rec->magvar, 0);
- pdb_write_float(&rec->elevation,
- METERS_TO_FEET(wpt->altitude));
-
- vdata = (char*)rec + sizeof(*rec);
- if (wpt->shortname) {
- strncpy(vdata, wpt->shortname, 10);
- vdata[9] = '\0';
- } else {
- vdata[0] ='\0';
- }
- vdata += strlen(vdata) + 1;
- if (wpt->description) {
- strncpy(vdata, wpt->description, 100);
- vdata[99] = '\0';
- } else {
- vdata[0] ='\0';
- }
- vdata += strlen(vdata) + 1;
-
- if (wpt->notes) {
- strncpy(vdata, wpt->notes, 1000);
- vdata[999] = '\0';
- } else {
- vdata[0] ='\0';
- }
- vdata += strlen(vdata) + 1;
-
- pdb_write_rec(file_out, 0, 2, ct++, rec, (char*)vdata - (char*)rec);
-
- xfree(rec);
-}
-
-static void
-data_write(void)
-{
- strncpy(file_out->name, out_fname, PDB_DBNAMELEN);
- file_out->name[PDB_DBNAMELEN-1] = 0;
- file_out->attr = PDB_FLAG_BACKUP;
- file_out->ctime = file_out->mtime = current_time().toTime_t() + 2082844800U;
- file_out->type = wayp_TYPE;
- file_out->creator = GXPU_CREATOR;
- file_out->version = 4;
-
- waypt_disp_all(copilot_writewpt);
-}
-
-
-ff_vecs_t copilot_vecs = {
- ff_type_file,
- FF_CAP_RW_WPT,
- rd_init,
- wr_init,
- rd_deinit,
- wr_deinit,
- data_read,
- data_write,
- NULL,
- NULL,
- CET_CHARSET_ASCII, 0 /* CET-REVIEW */
-};
-#endif
+++ /dev/null
-/*
- Read and write cotoGPS files.
-
- Copyright (C) 2005 Tobias Minich,
-
- Based on the Cetus I/O Filter,
- Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
-
- */
-
-
-#include "defs.h"
-#if PDBFMTS_ENABLED
-#include "csv_util.h"
-#include "pdbfile.h"
-#include "grtcirc.h"
-
-#define MYNAME "cotoGPS"
-
-#define MYTYPETRACK 0x5452434b /* TRCK */
-#define MYTYPEWPT 0x44415441 /* DATA */
-#define MYCREATOR 0x636f4750 /* coGP */
-
-#define NOTESZ 4096
-#define DESCSZ 4096
-
-#define MAX_MARKER_NAME_LENGTH 20
-#define CATEGORY_NAME_LENGTH 16
-
-typedef enum {
- cotofixNone = 0, /* No Fix or Warning */
- cotofixReserved = 1, /* Shouldn't occur*/
- cotofix2D = 2, /* retrieved from a GPS with a 2D fix */
- cotofix3D = 3, /* retrieved from a GPS with a 3D fix */
- cotofixDGPS = 4, /* retrieved from a GPS with a DGPS signal */
-} fix_quality;
-
-struct record_track {
-
- pdb_double latitude; /* radians, s=negative */
- pdb_double longitude; /* same as lat; e=negative */
- pdb_double distance; /* Distance to thel last point; discarded since it's calculated by gpsbabel on write */
- pdb_double arc; /* Course, unknown dimension */
- pdb_double x,y; /* Internal virtual coordinates used for drawing the track on the Palm */
-
- uint16_t alt; /* Altitude */
-
- /* accuracy and precision information for use where applicable */
- uint16_t hdop; /* _dop * 10 */
- uint16_t vdop;
- uint16_t pdop;
- uint8_t sat_tracked;
- uint8_t fix_quality;
-
- uint16_t speed; /* *10 */
- uint32_t time; /* Palm Time */
-};
-
-struct record_wpt {
- char lon[8];
- char lat[8];
- char name[MAX_MARKER_NAME_LENGTH];
- char notes[1];
-};
-
-
-// We need the pdb AppInfo for waypoint categories
-
-typedef char appinfo_category[16];
-
-typedef struct appinfo {
- uint8_t U0;
- uint8_t renamedCategories;
- appinfo_category categories[CATEGORY_NAME_LENGTH];
- uint8_t ids[16];
- uint8_t maxid;
-} appinfo_t;
-
-#define APPINFO_SIZE sizeof(appinfo_t)
-
-static pdbfile* file_in, *file_out;
-static const char* out_fname;
-static const char* in_fname; /* We might need that for naming tracks */
-static short_handle mkshort_wr_handle;
-static int ct;
-
-static char* zerocat = NULL;
-static char* internals = NULL;
-
-static
-arglist_t coto_args[] = {
- {
- "zerocat", &zerocat, "Name of the 'unassigned' category", NULL,
- ARGTYPE_STRING, ARG_NOMINMAX
- },
- {
- "internals", &internals, "Export some internal stuff to notes", NULL,
- ARGTYPE_STRING | ARGTYPE_HIDDEN, ARG_NOMINMAX
- },
- ARG_TERMINATOR
-};
-
-static void
-rd_init(const char* fname)
-{
- file_in = pdb_open(fname, MYNAME);
- in_fname = fname;
-}
-
-static void
-rd_deinit(void)
-{
- pdb_close(file_in);
-}
-
-static void
-wr_init(const char* fname)
-{
- file_out = pdb_create(fname, MYNAME);
- out_fname = fname;
- ct = 0;
-}
-
-static void
-wr_deinit(void)
-{
- // pdb_close() will only free appinfo in read mode, and pdb_create() sets the mode to write.
- struct appinfo* ai = (struct appinfo*) file_out->appinfo;
- pdb_close(file_out);
- if (ai) {
- free(ai);
- }
-}
-
-/* helpers */
-
-static QString
-coto_get_icon_descr(int category, const appinfo_t* app)
-{
- char buff[CATEGORY_NAME_LENGTH + 1] = "Not Assigned";
- if ((category >= 0) && (category < 16)) {
- if ((category > 0) && (app->categories[category][0] == '\0')) {
- category = 0;
- }
-
- strncpy(buff, app->categories[category], sizeof(buff) - 1);
- if (buff[0] == '\0') {
- return QString();
- }
- }
- return QString(buff);
-}
-
-static void
-coto_track_read(void)
-{
- struct record_track* rec;
- pdbrec_t* pdb_rec;
- route_head* trk_head;
- char* track_name;
-
- if (strncmp(file_in->name, "cotoGPS TrackDB", PDB_DBNAMELEN) != 0)
- // Use database name if not default
- {
- track_name = xstrndup(file_in->name, PDB_DBNAMELEN);
- } else {
- // Use filename for new track title
- const char* fnametmp = strrchr(in_fname, '/');
- if (fnametmp == NULL) {
- fnametmp = strrchr(in_fname, '\\');
- }
- if (fnametmp) {
- fnametmp++;
- } else {
- fnametmp = in_fname;
- }
- if (strrchr(fnametmp, '.') != NULL) {
- track_name = xstrndup(fnametmp, strrchr(fnametmp,'.') - fnametmp);
- } else {
- track_name = xstrdup(fnametmp);
- }
- }
-
- trk_head = route_head_alloc();
- track_add_head(trk_head);
-
- trk_head->rte_name = track_name;
-
- for (pdb_rec = file_in->rec_list; pdb_rec; pdb_rec = pdb_rec->next) {
- waypoint* wpt_tmp;
-
- wpt_tmp = waypt_new();
-
- rec = (struct record_track*) pdb_rec->data;
-
- wpt_tmp->longitude = DEG(-pdb_read_double(&rec->longitude));
- wpt_tmp->latitude = DEG(pdb_read_double(&rec->latitude));
-
- // It's not the course, so leave it out for now
- // WAYPT_SET(wpt_tmp, course, pdb_read_double(&rec->arc));
- wpt_tmp->altitude = be_read16(&rec->alt);
-
- if (internals) {
- // Parse the option as xcsv delimiter
- const char* inter = xcsv_get_char_from_constant_table(internals);
- char temp[256];
- snprintf(temp, sizeof(temp), "%.20f%s%.20f%s%.20f%s%.20f", pdb_read_double(&rec->distance), inter,
- pdb_read_double(&rec->arc), inter, pdb_read_double(&rec->x), inter, pdb_read_double(&rec->y));
- wpt_tmp->notes = xstrdup(temp);
- }
-
- wpt_tmp->pdop = be_read16(&rec->pdop)/10.0;
- wpt_tmp->hdop = be_read16(&rec->hdop)/10.0;
- wpt_tmp->vdop = be_read16(&rec->vdop)/10.0;
- wpt_tmp->sat = rec->sat_tracked;
- switch (rec->fix_quality) {
- case cotofixNone:
- wpt_tmp->fix = fix_none;
- break;
- case cotofixReserved:
- wpt_tmp->fix = fix_unknown;
- break;
- case cotofix2D:
- wpt_tmp->fix = fix_2d;
- break;
- case cotofix3D:
- wpt_tmp->fix = fix_3d;
- break;
- case cotofixDGPS:
- wpt_tmp->fix = fix_dgps;
- break;
- }
- WAYPT_SET(wpt_tmp, speed, be_read16(&rec->speed)/10.0);
- rec->time = be_read32(&rec->time);
- if (rec->time != 0) {
- rec->time -= 2082844800U;
- wpt_tmp->SetCreationTime(rec->time);
- }
- track_add_wpt(trk_head, wpt_tmp);
- }
-}
-
-static void
-coto_wpt_read(void)
-{
- struct record_wpt* rec;
- pdbrec_t* pdb_rec;
- appinfo_t* app;
- app = (struct appinfo*) file_in->appinfo;
-
- for (pdb_rec = file_in->rec_list; pdb_rec; pdb_rec = pdb_rec->next) {
- waypoint* wpt_tmp;
- char* c;
-
- wpt_tmp = waypt_new();
-
- rec = (struct record_wpt*) pdb_rec->data;
-
- wpt_tmp->longitude = DEG(-pdb_read_double(&rec->lon));
- wpt_tmp->latitude = DEG(pdb_read_double(&rec->lat));
-
- wpt_tmp->shortname = xstrndup(rec->name, sizeof(rec->name));
-
- wpt_tmp->icon_descr = coto_get_icon_descr(pdb_rec->category, app);
-
- if ((c = strstr(rec->notes, "\nNotes:\n"))) { /* remove our contruct */
- wpt_tmp->notes = xstrdup(c + 8);
- if (c != rec->notes) {
- wpt_tmp->description = xstrndup(rec->notes, c - rec->notes);
- }
- } else {
- wpt_tmp->notes = xstrdup(rec->notes);
- }
-
- waypt_add(wpt_tmp);
- }
-}
-
-static void
-data_read(void)
-{
- if ((file_in->creator != MYCREATOR) || ((file_in->type != MYTYPETRACK) && (file_in->type != MYTYPEWPT))) {
- warning("Creator %x Type %x Version %d\n", (int) file_in->creator, (int) file_in->type, (int) file_in->version);
- fatal(MYNAME ": Not a cotoGPS file.\n");
- }
-
- is_fatal((file_in->version > 0),
- MYNAME ": This file is from an unsupported newer version of cotoGPS. It may be supported in a newer version of GPSBabel.\n");
-
- switch (file_in->type) {
- case MYTYPETRACK:
- coto_track_read();
- break;
- case MYTYPEWPT:
- coto_wpt_read();
- break;
- }
-}
-
-static void
-coto_prepare_wpt_write(void)
-{
- struct appinfo* ai;
-
- file_out->name[PDB_DBNAMELEN-1] = 0;
- file_out->attr = PDB_FLAG_BACKUP;
- file_out->type = MYTYPEWPT;
- file_out->creator = MYCREATOR;
- file_out->version = 0;
-
- strncpy(file_out->name, "cotoGPS MarkerDB", PDB_DBNAMELEN);
-
- file_out->appinfo_len = APPINFO_SIZE;
- file_out->appinfo = calloc(APPINFO_SIZE,1);
-
- ai = (struct appinfo*) file_out->appinfo;
- be_write16(&ai->renamedCategories, 31); // Don't ask me why...
- if (zerocat) {
- strncpy(ai->categories[0], zerocat, 16);
- } else {
- strncpy(ai->categories[0], "Not Assigned", 16); // FIXME: Replace by default English Palm 'Not Assigned' category
- }
-
-}
-
-static void
-coto_wpt_write(const waypoint* wpt)
-{
- struct record_wpt* rec;
- struct appinfo* ai = (struct appinfo*) file_out->appinfo;
- char* notes = NULL;
- char* shortname = NULL;
- int size;
- uint8_t cat = 0;
- int i;
-
- mkshort_wr_handle = mkshort_new_handle();
- setshort_length(mkshort_wr_handle, MAX_MARKER_NAME_LENGTH);
- setshort_whitespace_ok(mkshort_wr_handle, 1);
-
- if ((global_opts.synthesize_shortnames && wpt->description) || (wpt->shortname == NULL)) {
- shortname = mkshort_from_wpt(mkshort_wr_handle, wpt);
- } else {
- shortname = xstrdup(wpt->shortname);
- }
-
- if ((wpt->description) && ((strlen(wpt->description) > MAX_MARKER_NAME_LENGTH) || (strcmp(wpt->description, wpt->shortname)))) {
- if ((wpt->notes) && (strcmp(wpt->description, wpt->notes) != 0)) {
- notes = (char*) xcalloc(strlen(wpt->description) + strlen(wpt->notes) + 9, 1);
- sprintf(notes, "%s\nNotes:\n%s", wpt->description, wpt->notes);
- } else {
- notes = xstrdup(wpt->description);
- }
- } else if (wpt->notes != NULL) {
- notes = xstrdup(wpt->notes);
- }
-
- size = sizeof(*rec);
- if (notes != NULL) {
- size += strlen(notes);
- }
- rec = (struct record_wpt*) xcalloc(size, 1);
-
- pdb_write_double(&rec->lon, RAD(-wpt->longitude));
- pdb_write_double(&rec->lat, RAD(wpt->latitude));
- strncpy(rec->name, shortname, MAX_MARKER_NAME_LENGTH);
-
- if (notes) {
- strcpy(rec->notes, notes);
- xfree(notes);
- }
-
- if (!wpt->icon_descr.isNull()) {
- for (i = 1; i < 16; i++)
- if (!strncmp(wpt->icon_descr.toUtf8().data(), ai->categories[i], 16)) {
- cat=i;
- break;
- }
- if (!cat) {
- // We have a new one
- if (ai->maxid<15) {
- i = ++ai->maxid;
- snprintf(ai->categories[i], 16, "%s", wpt->icon_descr.toUtf8().data());
- cat = ai->ids[i] = i;
- } else {
- // We're full!
- warning(MYNAME ": Categories full. Category '%s' written as %s.\n", wpt->icon_descr.toUtf8().data(), zerocat?zerocat:"Not Assigned");
- }
- }
- }
-
- pdb_write_rec(file_out, 0, cat, ct++, (const uint8_t*)rec, size);
-
- xfree(shortname);
- xfree(rec);
-
- mkshort_del_handle(&mkshort_wr_handle);
-}
-
-static void
-data_write(void)
-{
- coto_prepare_wpt_write();
- waypt_disp_all(coto_wpt_write);
-}
-
-
-ff_vecs_t coto_vecs = {
- ff_type_file,
- {(ff_cap)(ff_cap_read|ff_cap_write), ff_cap_read, ff_cap_none},
- rd_init,
- wr_init,
- rd_deinit,
- wr_deinit,
- data_read,
- data_write,
- NULL,
- coto_args,
- CET_CHARSET_ASCII, 0 /* CET-REVIEW */
-};
-#endif
--- /dev/null
+Every community needs a retirement home. deprecated/ is ours.
+
+This is where formats get moved once they become unused or are little used
+and problematic to refit into newer infrastructure. Formats are moved here
+so they remain examples for future developers or so that they can be revived
+by interested parties and updated in the future. As I am writing this, the
+formats being deleted are each under .02% (yes, the decimal is in the correct
+place) of our expected users.
+
+This allows us to modernize our core systems without getting bogged down
+in reimplementing formats that nobody[1] has used in years. It also allows
+us to more easily bring back formats if we were wrong on how popular something
+was.
+
+Epitaths
+
+* cetus, copilot, coto, gcdb, geoniche, gpilots, gpspilot, mag_pdb, magnav,
+ mapopolis, palmdoc, pathaway, pdbfile, quovadis: Palm/OS has been in decline
+ for years. We've seen no list traffic about these in years. Many of them
+ have particularly grubby internal implementations. None of these programs
+ have been updated since the demise of Palm/OS.
+* hsa_ndv: Zero list traffic from anyone other than original author,
+ who has quit responding to email, contributed it ten years ago.
+ Use of "raw" expat (which we're removing), strange structure, poor test
+ suite coverage. Company that created HSA is gone.
+* coastexp: Extremely little use (three posts since submitted ten years ago,
+ zero in the last five years) Uses expat. Probably easier to revive than
+ hsa_ndv if there's interest.
+* msroute: Long a problematic format when it was added in 2005. It read
+ Microsoft AutoRoute 2002 files. It somewhat worked until about 2007 but
+ pretty much every annual Microsoft update broke it. As AutoRoute and
+ Streets & Trips has added GPX, this format has outlived its usefulness.
+* psp: If desktop Microsoft S&T from 2002 was dead (see msroute)
+ PocketStreets 2002 Pushpin is even more dead. Not used or made in years.
+* axim_gpb: Dell Axim Navigation (their iPaq-wannabe) hasn't been used or
+ made in years. Usage stats are near zero.
+
+R.I.P.
+
+-- Robert Lipe
+
+[1] That's in the purely mathematical sense, not a personal one. We have
+ millions of users...
--- /dev/null
+/*
+ Read and write Cetus files.
+
+ Copyright (C) 2002-2008 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+/*
+
+ History:
+
+ 2005/08/03: Added track_read by O.K.
+ (Thanx to Adam Schneider for additional information)
+
+*/
+
+#include "defs.h"
+#if PDBFMTS_ENABLED
+#include "pdbfile.h"
+
+#define MYNAME "Cetus"
+#define MYTYPE_WPT 0x43577074 /* CWpt */
+#define MYTYPE_TRK 0x7374726d /* strm */
+
+#define MYCREATOR 0x63475053 /* cGPS */
+#define MYTRACK 0x44424c4b /* DBLK */
+
+#define NOTESZ 4096
+#define DESCSZ 4096
+
+typedef enum {
+ WptEdit = 0, /* the position has been edited or it was */
+ /* imported from another source */
+ WptGPS2D = 1, /* retrieved from a GPS with a 2D fix */
+ WptGPS3D = 2, /* retrieved from a GPS with a 3D fix */
+ WptDGPS2D = 3, /* retrieved from a GPS with a 2D fix and DGPS signal */
+ WptDGPS3D = 4, /* retrieved from a GPS with a 3D fix and DGPS signal */
+ WptAverage = 5, /* averaging over 3D positions */
+ WptCache = 50, /* this position is a geocache reference */
+ WptGarmin = 70 /* this position was imported from a Garmin GPS */
+ /* the icon field contains the garmin symbol number */
+} wpt_type;
+
+struct cetus_wpt_s {
+ char type;
+
+ char readonly;
+
+ pdb_32 latitude; /* Big endian, degrees*1e7, s=negative */
+ pdb_32 longitude; /* same as lat; w=negative */
+ pdb_32 elevation; /* Big endian, meters*100. blank=-1e8 */
+
+ pdb_16 year; /* sample time, UTC */
+ unsigned char mon;
+ unsigned char day;
+ unsigned char hour;
+ unsigned char min;
+ unsigned char sec;
+
+ /* accuracy and precision information for use where applicable */
+ unsigned char sat; /* ff if averaged or unknown */
+ pdb_16 pdop; /* pdop * 100 */
+ pdb_16 hdop;
+ pdb_16 vdop;
+ pdb_16 dgpstime;
+ pdb_32 dgpsstn;
+ pdb_32 avgtime;
+ pdb_32 avgite;
+
+ pdb_16 dopmask;
+ pdb_16 elevmask;
+
+ pdb_16 radius;
+ pdb_32 distance;
+
+ pdb_16 vyear; /* date visited */
+ unsigned char vmon;
+ unsigned char vday;
+ unsigned char vhour;
+ unsigned char vmin;
+ unsigned char vsec;
+
+ char flagged;
+
+ pdb_32 icon;
+ pdb_16 category;
+};
+
+typedef struct cetus_track_head_s {
+ char id[2];
+ char version;
+ unsigned char interval;
+ unsigned short gps;
+ char year;
+ char month;
+ char day;
+ char hour;
+ char min;
+ char sec;
+ char dsec;
+ char tz;
+ char desc;
+} cetus_track_head_t;
+
+#define TRACK_HEAD_SIZE sizeof(struct cetus_track_head_s)
+
+typedef struct cetus_track_point_s {
+ signed char hour;
+ signed char min;
+ signed char sec;
+ signed char dsec;
+ signed char sat;
+ signed char hdop;
+ pdb_32 latitude;
+ pdb_32 longitude;
+ short speed;
+ short course;
+ pdb_32 elevation;
+} cetus_track_point_t;
+
+#define TRACK_POINT_SIZE sizeof(struct cetus_track_point_s)
+
+static pdbfile* file_in, *file_out;
+static const char* out_fname;
+static short_handle mkshort_wr_handle;
+static int ct;
+
+static char* dbname = NULL;
+static char* appendicon = NULL;
+
+static
+arglist_t cetus_args[] = {
+ {
+ "dbname", &dbname, "Database name", NULL, ARGTYPE_STRING,
+ ARG_NOMINMAX
+ },
+ {
+ "appendicon", &appendicon, "Append icon_descr to description",
+ NULL, ARGTYPE_BOOL, ARG_NOMINMAX
+ },
+ ARG_TERMINATOR
+};
+
+static waypoint*
+read_track_point(cetus_track_point_t* data, const time_t basetime)
+{
+ int i, ilat, ilon;
+ waypoint* wpt;
+
+ ilat = be_read32(&data->latitude);
+ ilon = be_read32(&data->longitude);
+
+ if (data->hour == -1 || data->min == -1 || data->sec == -1 ||
+ ilat == 2000000000 || ilon == 2000000000) {
+ return NULL; /* At least one of basic data is not available */
+ }
+
+ wpt = waypt_new();
+
+ wpt->latitude = (double)ilat / 10000000.0;
+ wpt->longitude = (double)ilon / 10000000.0;
+
+ i = be_read32(&data->elevation);
+ wpt->altitude = (i == -100000000) ? unknown_alt : (double) i / 100.0;
+
+ if (data->sat != -1) {
+ wpt->sat = data->sat;
+ }
+ if (data->hdop != -1) {
+ wpt->hdop = (float) data->hdop / 10;
+ }
+
+ i = be_read16(&data->speed);
+ if (i != 10000) {
+ WAYPT_SET(wpt, speed, KNOTS_TO_MPS((double) i / 10.0)); /* meters/second */
+ }
+ i = be_read16(&data->course);
+ if (i != 4000) {
+ WAYPT_SET(wpt, course, (float) i / 10);
+ }
+
+ switch (data->hour >> 5) { /* extract fix */
+ case 1:
+ wpt->fix = fix_none;
+ break;
+ case 2:
+ wpt->fix = fix_2d;
+ break;
+ case 3:
+ wpt->fix = fix_3d;
+ break;
+ case 4:
+ wpt->fix = fix_dgps;
+ break;
+ default:
+ break; /* no GPS */
+ }
+
+ wpt->SetCreationTime(basetime +
+ ((data->hour & 0x1F) * 3600) + (data->min * 60) + data->sec, data->dsec * 10);
+
+ return wpt;
+}
+
+
+static void
+read_tracks(const pdbfile* pdb)
+{
+ pdbrec_t* pdb_rec;
+ int reclen, records, total, points, dropped;
+ char descr[(2 * TRACK_POINT_SIZE) + 1];
+ char temp_descr[TRACK_POINT_SIZE + 1];
+ cetus_track_head_t* head;
+ waypoint* wpt;
+ route_head* track;
+ time_t basetime;
+
+ track = route_head_alloc();
+ track_add_head(track);
+
+ total = 0;
+ points = 0;
+ dropped = 0;
+ basetime = 0;
+
+ for (pdb_rec = pdb->rec_list; pdb_rec; pdb_rec = pdb_rec->next) {
+ int i, magic;
+ char* c = (char*)pdb_rec->data;
+
+ magic = be_read32(c);
+ if (magic != MYTRACK) {
+ fatal(MYNAME ": Invaid track data or unsupported version!\n");
+ }
+
+ reclen = be_read32(c+4);
+ records = reclen / TRACK_POINT_SIZE;
+
+ c += 8;
+
+ for (i = 0; i < records; i++, c += TRACK_POINT_SIZE) {
+ switch (total++) {
+ struct tm tm;
+
+ case 0: /* track header */
+ head = (cetus_track_head_t*)c;
+ if (head->id[0] != 'C' || head->id[1] != 'G') {
+ fatal(MYNAME ": Invalid track header!\n");
+ }
+
+ memset(&tm, 0, sizeof(tm));
+ tm.tm_mday = head->day;
+ tm.tm_mon = head->month - 1;
+ tm.tm_year = head->year + 100;
+ basetime = mkgmtime(&tm);
+ break;
+
+ case 1: /* first part of description */
+ strncpy(descr, c, TRACK_POINT_SIZE);
+ break;
+
+ case 2: /* continued description */
+ strncpy(temp_descr, c, TRACK_POINT_SIZE);
+ strcat(descr, temp_descr); /* here is no need to check target size */
+ if (strlen(descr) > 0) {
+ track->rte_desc = xstrdup(descr);
+ }
+ break;
+
+ default:
+ wpt = read_track_point((cetus_track_point_t*)c, basetime);
+ if (wpt != NULL) {
+ track_add_wpt(track, wpt);
+ points++;
+ } else {
+ dropped++;
+ }
+ }
+
+ }
+ }
+
+ if (global_opts.verbose_status > 0) {
+ printf(MYNAME ": Loaded %d track point(s) from source.\n", points);
+ if (dropped > 0) {
+ printf(MYNAME ": ! %d dropped because of missing data (no time, no coordinates) !\n", dropped);
+ }
+ }
+}
+
+static void
+read_waypts(const pdbfile* pdb)
+{
+ struct cetus_wpt_s* rec;
+ pdbrec_t* pdb_rec;
+ char* vdata;
+
+ for (pdb_rec = pdb->rec_list; pdb_rec; pdb_rec = pdb_rec->next) {
+ waypoint* wpt_tmp;
+ int i;
+
+ wpt_tmp = waypt_new();
+
+ rec = (struct cetus_wpt_s*) pdb_rec->data;
+ if (be_read32(&rec->elevation) == -100000000) {
+ wpt_tmp->altitude = unknown_alt;
+ } else {
+ wpt_tmp->altitude = be_read32(&rec->elevation) / 100.0;
+ }
+
+ wpt_tmp->latitude = be_read32(&rec->latitude) / 10000000.0;
+ wpt_tmp->longitude = be_read32(&rec->longitude) / 10000000.0;
+
+ if (rec->sat != 0xff) {
+ wpt_tmp->sat = rec->sat;
+ }
+
+ i = be_read16(&rec->pdop);
+ if (i != 0xffff) {
+ wpt_tmp->pdop = i / 100.0;
+ }
+ i = be_read16(&rec->hdop);
+ if (i != 0xffff) {
+ wpt_tmp->hdop = i / 100.0;
+ }
+ i = be_read16(&rec->vdop);
+ if (i != 0xffff) {
+ wpt_tmp->vdop = i / 100.0;
+ }
+
+ switch (rec->type) {
+ case WptGPS2D:
+ wpt_tmp->fix = fix_2d;
+ break;
+ case WptGPS3D:
+ wpt_tmp->fix = fix_3d;
+ break;
+ case WptDGPS2D:
+ wpt_tmp->fix = fix_dgps;
+ break;
+ case WptDGPS3D:
+ wpt_tmp->fix = fix_dgps;
+ break;
+ }
+
+ if (be_read16(&rec->year) != 0xff) {
+ struct tm tm;
+
+ memset(&tm, 0, sizeof(tm));
+ tm.tm_min = rec->min;
+ tm.tm_hour = rec->hour;
+ tm.tm_mday = rec->day;
+ tm.tm_mon = rec->mon - 1;
+ tm.tm_year = be_read16(&rec->year) - 1900;
+
+ wpt_tmp->SetCreationTime(mkgmtime(&tm));
+
+ }
+
+ vdata = (char*) pdb_rec->data + sizeof(*rec);
+
+ wpt_tmp->shortname = xstrdup(vdata);
+ vdata = vdata + strlen(vdata) + 1;
+
+ wpt_tmp->description = xstrdup(vdata);
+ vdata = vdata + strlen(vdata) + 1;
+
+ wpt_tmp->notes = xstrdup(vdata);
+
+ waypt_add(wpt_tmp);
+
+ }
+}
+
+/* --------------------------------------------------------------------------- */
+
+static void
+rd_init(const char* fname)
+{
+ file_in = pdb_open(fname, MYNAME);
+}
+
+static void
+rd_deinit(void)
+{
+ pdb_close(file_in);
+ if (dbname) {
+ xfree(dbname);
+ dbname = NULL;
+ }
+}
+
+static void
+wr_init(const char* fname)
+{
+ file_out = pdb_create(fname, MYNAME);
+ out_fname = fname;
+ ct = 0;
+}
+
+static void
+wr_deinit(void)
+{
+ pdb_close(file_out);
+ if (dbname) {
+ xfree(dbname);
+ dbname = NULL;
+ }
+}
+
+static void
+data_read(void)
+{
+ if (file_in->creator != MYCREATOR) {
+ fatal(MYNAME ": Not a Cetus file.\n");
+ }
+
+ switch (file_in->type) {
+ case MYTYPE_TRK:
+ read_tracks(file_in);
+ break;
+
+ case MYTYPE_WPT:
+ read_waypts(file_in);
+ break;
+ }
+}
+
+
+static void
+cetus_writewpt(const waypoint* wpt)
+{
+ struct cetus_wpt_s* rec;
+ char* vdata;
+ char* desc_long;
+ char* desc_short;
+ char* desc_geo;
+ char* desc;
+
+ rec = (struct cetus_wpt_s*) xcalloc(sizeof(*rec)+18 + NOTESZ + DESCSZ,1);
+
+ QDate date(wpt->GetCreationTime().date());
+ rec->day = date.day();
+ rec->mon = date.month();
+ be_write16(&rec->year, date.year());
+
+ QTime time(wpt->GetCreationTime().time());
+ rec->min = time.minute();
+ rec->hour = time.hour();
+ rec->sec = time.second();
+
+ be_write32(&rec->longitude, (unsigned int)(int)(wpt->longitude * 10000000.0));
+ be_write32(&rec->latitude, (unsigned int)(wpt->latitude * 10000000.0));
+ if (wpt->altitude == unknown_alt) {
+ be_write32(&rec->elevation, -100000000);
+ } else {
+ be_write32(&rec->elevation, (unsigned int)(wpt->altitude * 100.0));
+ }
+
+ be_write16(&rec->pdop, wpt->pdop ? wpt->pdop * 100 : 0xffff);
+ be_write16(&rec->hdop, wpt->hdop ? wpt->hdop * 100 : 0xffff);
+ be_write16(&rec->vdop, wpt->vdop ? wpt->vdop * 100 : 0xffff);
+ be_write16(&rec->dgpstime, 0xffff);
+ be_write32(&rec->distance, 0xffffffff);
+
+ rec->vmin = 0xff;
+ rec->vhour = 0xff;
+ rec->vsec = 0xff;
+ rec->vday = 0xff;
+ rec->vmon = 0xff;
+ be_write16(&rec->vyear, 0xff);
+
+ rec->sat = wpt->sat ? wpt->sat : 0xff;
+
+ vdata = (char*)rec + sizeof(*rec);
+ if (wpt->shortname) {
+ char* sn = xstrdup(wpt->shortname);
+ strncpy(vdata, sn, 16);
+ vdata[15] = '\0';
+ xfree(sn);
+ } else {
+ vdata[0] ='\0';
+ }
+ vdata += strlen(vdata) + 1;
+
+ if (wpt->gc_data->diff) {
+ xasprintf(&desc_geo, "%s%s by %s\n%.4s/%.4s %3.1f/%3.1f\n",
+ wpt->gc_data->is_available==status_true ?
+ "" : " (Disabled)",
+ wpt->gc_data->is_archived==status_true ?
+ " (Archived)" : "",
+ wpt->gc_data->placer.toUtf8().data(),
+ gs_get_cachetype(wpt->gc_data->type),
+ gs_get_container(wpt->gc_data->container),
+ wpt->gc_data->diff/10.0,
+ wpt->gc_data->terr/10.0);
+ } else {
+ desc_geo = xstrdup("");
+ }
+
+ if (!wpt->gc_data->desc_short.utfstring.isEmpty()) {
+ char* stripped_html = strip_html(&wpt->gc_data->desc_short);
+ desc_short = xstrdup(wpt->gc_data->diff == 0 ? "\n\n" : "");
+ desc_short = xstrappend(desc_short, xstrdup(stripped_html));
+ xfree(stripped_html);
+ } else {
+ desc_short = xstrdup("");
+ }
+
+ if (!wpt->gc_data->desc_long.utfstring.isEmpty()) {
+ char* stripped_html = strip_html(&wpt->gc_data->desc_long);
+ desc_long = xstrdup("\n\n");
+ desc_long = xstrappend(desc_long, xstrdup(stripped_html));
+ xfree(stripped_html);
+ } else {
+ desc_long = xstrdup("");
+ }
+
+ desc = wpt->description ? xstrdup(wpt->description) :
+ xstrdup("");
+
+ snprintf(vdata, DESCSZ, "%s%s%s%s",
+ desc,
+ desc_geo,
+ desc_short,
+ desc_long);
+
+ xfree(desc);
+ xfree(desc_geo);
+ xfree(desc_short);
+ xfree(desc_long);
+
+ if (appendicon && !wpt->icon_descr.isNull()) {
+ int left = DESCSZ - strlen(vdata);
+ int ilen = strlen(wpt->icon_descr.toUtf8().data());
+ if (ilen && left > (ilen+3)) {
+ strcat(vdata, " (");
+ strcat(vdata, wpt->icon_descr.toUtf8().data());
+ strcat(vdata, ")");
+ }
+ }
+ vdata += strlen(vdata) + 1;
+
+ if (!wpt->gc_data->hint.isEmpty()) {
+ char* hint = xstrdup(wpt->gc_data->hint.toUtf8().data());
+ rec->type = WptCache;
+ strncpy(vdata, hint, NOTESZ + 1) ;
+ xfree(hint);
+ vdata[NOTESZ] = '\0';
+ } else {
+ rec->type = WptEdit;
+ vdata[0] ='\0';
+ }
+ vdata += strlen(vdata) + 1;
+
+ pdb_write_rec(file_out, 0, 2, ct++, rec, (char*)vdata - (char*)rec);
+
+ xfree(rec);
+}
+
+struct hdr {
+ char* wpt_name;
+ waypoint* wpt;
+};
+
+static
+int
+compare(const void* a, const void* b)
+{
+ const struct hdr* wa = (const struct hdr*) a;
+ const struct hdr* wb = (const struct hdr*) b;
+
+ return strcmp(wa->wpt->shortname, wb->wpt->shortname);
+}
+
+static void
+data_write(void)
+{
+ int i, ct = waypt_count();
+ struct hdr* htable, *bh;
+ queue* elem, *tmp;
+ extern queue waypt_head;
+ waypoint* waypointp;
+ mkshort_wr_handle = mkshort_new_handle();
+ setshort_length(mkshort_wr_handle, 15);
+ setshort_whitespace_ok(mkshort_wr_handle, 0);
+
+ if (dbname) {
+ strncpy(file_out->name, dbname, PDB_DBNAMELEN);
+ } else {
+ strncpy(file_out->name, out_fname, PDB_DBNAMELEN);
+ }
+ file_out->name[PDB_DBNAMELEN-1] = 0;
+ file_out->attr = PDB_FLAG_BACKUP;
+ file_out->ctime = file_out->mtime = current_time().toTime_t() + 2082844800U;
+ file_out->type = MYTYPE_WPT; /* CWpt */
+ file_out->creator = MYCREATOR; /* cGPS */
+ file_out->version = 1;
+
+ /*
+ * All this is to sort by waypoint names before going to Cetus.
+ * Turns out plain old strcmp will do the trick...
+ */
+
+ htable = (struct hdr*) xmalloc(ct * sizeof(*htable));
+ bh = htable;
+
+ QUEUE_FOR_EACH(&waypt_head, elem, tmp) {
+ waypointp = (waypoint*) elem;
+ bh->wpt = waypointp;
+ if (global_opts.synthesize_shortnames && waypointp->description) {
+ if (waypointp->shortname) {
+ xfree(waypointp->shortname);
+ }
+ waypointp->shortname = mkshort_from_wpt(mkshort_wr_handle, waypointp);
+ }
+ bh->wpt_name = waypointp->shortname;
+ bh ++;
+ }
+ qsort(htable, ct, sizeof(*bh), compare);
+
+ for (i=0; i<ct; i++) {
+ cetus_writewpt(htable[i].wpt);
+ }
+
+ xfree(htable);
+ mkshort_del_handle(&mkshort_wr_handle);
+}
+
+
+ff_vecs_t cetus_vecs = {
+ ff_type_file,
+ { (ff_cap)(ff_cap_write | ff_cap_read), ff_cap_read, ff_cap_none },
+ rd_init,
+ wr_init,
+ rd_deinit,
+ wr_deinit,
+ data_read,
+ data_write,
+ NULL,
+ cetus_args,
+ CET_CHARSET_MS_ANSI, 0 /* CET-REVIEW */
+};
+#endif
--- /dev/null
+/*
+ Read and write CoPilot files.
+
+ Copyright (C) 2002 Paul Tomblin, ptomblin@xcski.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+#if PDBFMTS_ENABLED
+#include "pdbfile.h"
+#include "grtcirc.h"
+
+#define MYNAME "CoPilot Waypoint"
+#define wayp_TYPE 0x77617970 /* wayp */
+#define wayu_TYPE 0x77617975 /* wayu */
+#define swpu_TYPE 0x73777075 /* swpu */
+#define GXPU_CREATOR 0x47584255 /* GXBU */
+#define AP_P_CREATOR 0x41502d50 /* AP-P */
+
+
+struct record0 {
+ pdb_double latitude; /* PDB double format, */
+ pdb_double longitude; /* similarly, neg = east */
+ pdb_double magvar; /* magnetic variation in degrees, neg = east */
+ uint32_t elevation; /* feet */
+};
+
+struct record1 {
+ pdb_double latitude; /* PDB double format, */
+ pdb_double longitude; /* similarly, neg = east */
+ pdb_double magvar; /* magnetic variation in degrees, neg = east */
+ pdb_double elevation; /* feet */
+};
+
+struct record3 {
+ pdb_double latitude; /* PDB double format, */
+ pdb_double longitude; /* similarly, neg = east */
+ pdb_double magvar; /* magnetic variation in degrees, neg = east */
+ pdb_double elevation; /* feet */
+ char flags; /* flags */
+};
+
+struct record4 {
+ pdb_double latitude; /* PDB double format, */
+ pdb_double longitude; /* similarly, neg = east */
+ pdb_float magvar; /* magnetic variation in degrees, neg = east */
+ pdb_float elevation; /* feet */
+};
+
+static pdbfile* file_in, *file_out;
+static const char* out_fname;
+static int ct;
+
+static void
+rd_init(const char* fname)
+{
+ file_in = pdb_open(fname, MYNAME);
+}
+
+static void
+rd_deinit(void)
+{
+ pdb_close(file_in);
+}
+
+static void
+wr_init(const char* fname)
+{
+ file_out = pdb_create(fname, MYNAME);
+ out_fname = fname;
+ ct = 0;
+}
+
+static void
+wr_deinit(void)
+{
+ pdb_close(file_out);
+}
+
+static waypoint*
+read_version0(void* data)
+{
+ char* vdata;
+ waypoint* wpt_tmp;
+ struct record0* rec = (struct record0*)data;
+
+ wpt_tmp = waypt_new();
+
+ wpt_tmp->longitude =
+ DEG(-pdb_read_double(&rec->longitude));
+ wpt_tmp->latitude =
+ DEG(pdb_read_double(&rec->latitude));
+ wpt_tmp->altitude = FEET_TO_METERS(be_read32(&rec->elevation));
+
+ vdata = (char*) data + sizeof(*rec);
+
+ wpt_tmp->shortname = xstrdup(vdata);
+ vdata = vdata + strlen(vdata) + 1;
+
+ wpt_tmp->description = xstrdup(vdata);
+ vdata = vdata + strlen(vdata) + 1;
+
+ wpt_tmp->notes = NULL;
+
+ return wpt_tmp;
+}
+
+static waypoint*
+read_version1(void* data)
+{
+ char* vdata;
+ waypoint* wpt_tmp;
+ struct record1* rec = (struct record1*)data;
+
+ wpt_tmp = waypt_new();
+
+ wpt_tmp->longitude =
+ DEG(-pdb_read_double(&rec->longitude));
+ wpt_tmp->latitude =
+ DEG(pdb_read_double(&rec->latitude));
+ wpt_tmp->altitude =
+ FEET_TO_METERS(pdb_read_double(&rec->elevation));
+
+ vdata = (char*) data + sizeof(*rec);
+
+ wpt_tmp->shortname = xstrdup(vdata);
+ vdata = vdata + strlen(vdata) + 1;
+
+ wpt_tmp->description = xstrdup(vdata);
+ vdata = vdata + strlen(vdata) + 1;
+
+ wpt_tmp->notes = xstrdup(vdata);
+
+ return wpt_tmp;
+}
+
+static waypoint*
+read_version3(void* data)
+{
+ char* vdata;
+ waypoint* wpt_tmp;
+ struct record3* rec = (struct record3*)data;
+
+ wpt_tmp = waypt_new();
+
+ wpt_tmp->longitude =
+ DEG(-pdb_read_double(&rec->longitude));
+ wpt_tmp->latitude =
+ DEG(pdb_read_double(&rec->latitude));
+ wpt_tmp->altitude =
+ FEET_TO_METERS(pdb_read_double(&rec->elevation));
+
+ vdata = (char*) data + sizeof(*rec);
+
+ wpt_tmp->shortname = xstrdup(vdata);
+ vdata = vdata + strlen(vdata) + 1;
+
+ wpt_tmp->description = xstrdup(vdata);
+ vdata = vdata + strlen(vdata) + 1;
+
+ wpt_tmp->notes = xstrdup(vdata);
+
+ return wpt_tmp;
+}
+
+static waypoint*
+read_version4(void* data)
+{
+ char* vdata;
+ waypoint* wpt_tmp;
+ struct record4* rec = (struct record4*)data;
+
+ wpt_tmp = waypt_new();
+
+ wpt_tmp->longitude =
+ DEG(-pdb_read_double(&rec->longitude));
+ wpt_tmp->latitude =
+ DEG(pdb_read_double(&rec->latitude));
+ wpt_tmp->altitude =
+ FEET_TO_METERS(pdb_read_float(&rec->elevation));
+
+ vdata = (char*) data + sizeof(*rec);
+
+ wpt_tmp->shortname = xstrdup(vdata);
+ vdata = vdata + strlen(vdata) + 1;
+
+ wpt_tmp->description = xstrdup(vdata);
+ vdata = vdata + strlen(vdata) + 1;
+
+ wpt_tmp->notes = xstrdup(vdata);
+
+ return wpt_tmp;
+}
+
+static void
+data_read(void)
+{
+ pdbrec_t* pdb_rec;
+
+ if ((file_in->creator != GXPU_CREATOR && file_in->creator != AP_P_CREATOR) ||
+ (file_in->type != wayp_TYPE && file_in->type != swpu_TYPE &&
+ file_in->type != wayu_TYPE)) {
+ fatal(MYNAME ": Not a CoPilot file.\n");
+ }
+ if (file_in->version > 4) {
+ fatal(MYNAME ": %d is not a known version.\n", file_in->version);
+ }
+
+
+ for (pdb_rec = file_in->rec_list; pdb_rec; pdb_rec = pdb_rec->next) {
+ waypoint* wpt_tmp;
+
+ switch (file_in->version) {
+ case 0:
+ wpt_tmp = read_version0(pdb_rec->data);
+ break;
+ case 1:
+ case 2:
+ wpt_tmp = read_version1(pdb_rec->data);
+ break;
+ case 3:
+ wpt_tmp = read_version3(pdb_rec->data);
+ break;
+ case 4:
+ wpt_tmp = read_version4(pdb_rec->data);
+ break;
+ default:
+ fatal(MYNAME ": Unknown version %d.\n", file_in->version);
+ }
+ waypt_add(wpt_tmp);
+ }
+}
+
+static void
+copilot_writewpt(const waypoint* wpt)
+{
+ struct record4* rec;
+ char* vdata;
+
+ rec = (struct record4*) xcalloc(sizeof(*rec)+1141,1);
+
+ pdb_write_double(&rec->latitude, RAD(wpt->latitude));
+ pdb_write_double(&rec->longitude, RAD(-wpt->longitude));
+ pdb_write_float(&rec->magvar, 0);
+ pdb_write_float(&rec->elevation,
+ METERS_TO_FEET(wpt->altitude));
+
+ vdata = (char*)rec + sizeof(*rec);
+ if (wpt->shortname) {
+ strncpy(vdata, wpt->shortname, 10);
+ vdata[9] = '\0';
+ } else {
+ vdata[0] ='\0';
+ }
+ vdata += strlen(vdata) + 1;
+ if (wpt->description) {
+ strncpy(vdata, wpt->description, 100);
+ vdata[99] = '\0';
+ } else {
+ vdata[0] ='\0';
+ }
+ vdata += strlen(vdata) + 1;
+
+ if (wpt->notes) {
+ strncpy(vdata, wpt->notes, 1000);
+ vdata[999] = '\0';
+ } else {
+ vdata[0] ='\0';
+ }
+ vdata += strlen(vdata) + 1;
+
+ pdb_write_rec(file_out, 0, 2, ct++, rec, (char*)vdata - (char*)rec);
+
+ xfree(rec);
+}
+
+static void
+data_write(void)
+{
+ strncpy(file_out->name, out_fname, PDB_DBNAMELEN);
+ file_out->name[PDB_DBNAMELEN-1] = 0;
+ file_out->attr = PDB_FLAG_BACKUP;
+ file_out->ctime = file_out->mtime = current_time().toTime_t() + 2082844800U;
+ file_out->type = wayp_TYPE;
+ file_out->creator = GXPU_CREATOR;
+ file_out->version = 4;
+
+ waypt_disp_all(copilot_writewpt);
+}
+
+
+ff_vecs_t copilot_vecs = {
+ ff_type_file,
+ FF_CAP_RW_WPT,
+ rd_init,
+ wr_init,
+ rd_deinit,
+ wr_deinit,
+ data_read,
+ data_write,
+ NULL,
+ NULL,
+ CET_CHARSET_ASCII, 0 /* CET-REVIEW */
+};
+#endif
--- /dev/null
+/*
+ Read and write cotoGPS files.
+
+ Copyright (C) 2005 Tobias Minich,
+
+ Based on the Cetus I/O Filter,
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+
+#include "defs.h"
+#if PDBFMTS_ENABLED
+#include "csv_util.h"
+#include "pdbfile.h"
+#include "grtcirc.h"
+
+#define MYNAME "cotoGPS"
+
+#define MYTYPETRACK 0x5452434b /* TRCK */
+#define MYTYPEWPT 0x44415441 /* DATA */
+#define MYCREATOR 0x636f4750 /* coGP */
+
+#define NOTESZ 4096
+#define DESCSZ 4096
+
+#define MAX_MARKER_NAME_LENGTH 20
+#define CATEGORY_NAME_LENGTH 16
+
+typedef enum {
+ cotofixNone = 0, /* No Fix or Warning */
+ cotofixReserved = 1, /* Shouldn't occur*/
+ cotofix2D = 2, /* retrieved from a GPS with a 2D fix */
+ cotofix3D = 3, /* retrieved from a GPS with a 3D fix */
+ cotofixDGPS = 4, /* retrieved from a GPS with a DGPS signal */
+} fix_quality;
+
+struct record_track {
+
+ pdb_double latitude; /* radians, s=negative */
+ pdb_double longitude; /* same as lat; e=negative */
+ pdb_double distance; /* Distance to thel last point; discarded since it's calculated by gpsbabel on write */
+ pdb_double arc; /* Course, unknown dimension */
+ pdb_double x,y; /* Internal virtual coordinates used for drawing the track on the Palm */
+
+ uint16_t alt; /* Altitude */
+
+ /* accuracy and precision information for use where applicable */
+ uint16_t hdop; /* _dop * 10 */
+ uint16_t vdop;
+ uint16_t pdop;
+ uint8_t sat_tracked;
+ uint8_t fix_quality;
+
+ uint16_t speed; /* *10 */
+ uint32_t time; /* Palm Time */
+};
+
+struct record_wpt {
+ char lon[8];
+ char lat[8];
+ char name[MAX_MARKER_NAME_LENGTH];
+ char notes[1];
+};
+
+
+// We need the pdb AppInfo for waypoint categories
+
+typedef char appinfo_category[16];
+
+typedef struct appinfo {
+ uint8_t U0;
+ uint8_t renamedCategories;
+ appinfo_category categories[CATEGORY_NAME_LENGTH];
+ uint8_t ids[16];
+ uint8_t maxid;
+} appinfo_t;
+
+#define APPINFO_SIZE sizeof(appinfo_t)
+
+static pdbfile* file_in, *file_out;
+static const char* out_fname;
+static const char* in_fname; /* We might need that for naming tracks */
+static short_handle mkshort_wr_handle;
+static int ct;
+
+static char* zerocat = NULL;
+static char* internals = NULL;
+
+static
+arglist_t coto_args[] = {
+ {
+ "zerocat", &zerocat, "Name of the 'unassigned' category", NULL,
+ ARGTYPE_STRING, ARG_NOMINMAX
+ },
+ {
+ "internals", &internals, "Export some internal stuff to notes", NULL,
+ ARGTYPE_STRING | ARGTYPE_HIDDEN, ARG_NOMINMAX
+ },
+ ARG_TERMINATOR
+};
+
+static void
+rd_init(const char* fname)
+{
+ file_in = pdb_open(fname, MYNAME);
+ in_fname = fname;
+}
+
+static void
+rd_deinit(void)
+{
+ pdb_close(file_in);
+}
+
+static void
+wr_init(const char* fname)
+{
+ file_out = pdb_create(fname, MYNAME);
+ out_fname = fname;
+ ct = 0;
+}
+
+static void
+wr_deinit(void)
+{
+ // pdb_close() will only free appinfo in read mode, and pdb_create() sets the mode to write.
+ struct appinfo* ai = (struct appinfo*) file_out->appinfo;
+ pdb_close(file_out);
+ if (ai) {
+ free(ai);
+ }
+}
+
+/* helpers */
+
+static QString
+coto_get_icon_descr(int category, const appinfo_t* app)
+{
+ char buff[CATEGORY_NAME_LENGTH + 1] = "Not Assigned";
+ if ((category >= 0) && (category < 16)) {
+ if ((category > 0) && (app->categories[category][0] == '\0')) {
+ category = 0;
+ }
+
+ strncpy(buff, app->categories[category], sizeof(buff) - 1);
+ if (buff[0] == '\0') {
+ return QString();
+ }
+ }
+ return QString(buff);
+}
+
+static void
+coto_track_read(void)
+{
+ struct record_track* rec;
+ pdbrec_t* pdb_rec;
+ route_head* trk_head;
+ char* track_name;
+
+ if (strncmp(file_in->name, "cotoGPS TrackDB", PDB_DBNAMELEN) != 0)
+ // Use database name if not default
+ {
+ track_name = xstrndup(file_in->name, PDB_DBNAMELEN);
+ } else {
+ // Use filename for new track title
+ const char* fnametmp = strrchr(in_fname, '/');
+ if (fnametmp == NULL) {
+ fnametmp = strrchr(in_fname, '\\');
+ }
+ if (fnametmp) {
+ fnametmp++;
+ } else {
+ fnametmp = in_fname;
+ }
+ if (strrchr(fnametmp, '.') != NULL) {
+ track_name = xstrndup(fnametmp, strrchr(fnametmp,'.') - fnametmp);
+ } else {
+ track_name = xstrdup(fnametmp);
+ }
+ }
+
+ trk_head = route_head_alloc();
+ track_add_head(trk_head);
+
+ trk_head->rte_name = track_name;
+
+ for (pdb_rec = file_in->rec_list; pdb_rec; pdb_rec = pdb_rec->next) {
+ waypoint* wpt_tmp;
+
+ wpt_tmp = waypt_new();
+
+ rec = (struct record_track*) pdb_rec->data;
+
+ wpt_tmp->longitude = DEG(-pdb_read_double(&rec->longitude));
+ wpt_tmp->latitude = DEG(pdb_read_double(&rec->latitude));
+
+ // It's not the course, so leave it out for now
+ // WAYPT_SET(wpt_tmp, course, pdb_read_double(&rec->arc));
+ wpt_tmp->altitude = be_read16(&rec->alt);
+
+ if (internals) {
+ // Parse the option as xcsv delimiter
+ const char* inter = xcsv_get_char_from_constant_table(internals);
+ char temp[256];
+ snprintf(temp, sizeof(temp), "%.20f%s%.20f%s%.20f%s%.20f", pdb_read_double(&rec->distance), inter,
+ pdb_read_double(&rec->arc), inter, pdb_read_double(&rec->x), inter, pdb_read_double(&rec->y));
+ wpt_tmp->notes = xstrdup(temp);
+ }
+
+ wpt_tmp->pdop = be_read16(&rec->pdop)/10.0;
+ wpt_tmp->hdop = be_read16(&rec->hdop)/10.0;
+ wpt_tmp->vdop = be_read16(&rec->vdop)/10.0;
+ wpt_tmp->sat = rec->sat_tracked;
+ switch (rec->fix_quality) {
+ case cotofixNone:
+ wpt_tmp->fix = fix_none;
+ break;
+ case cotofixReserved:
+ wpt_tmp->fix = fix_unknown;
+ break;
+ case cotofix2D:
+ wpt_tmp->fix = fix_2d;
+ break;
+ case cotofix3D:
+ wpt_tmp->fix = fix_3d;
+ break;
+ case cotofixDGPS:
+ wpt_tmp->fix = fix_dgps;
+ break;
+ }
+ WAYPT_SET(wpt_tmp, speed, be_read16(&rec->speed)/10.0);
+ rec->time = be_read32(&rec->time);
+ if (rec->time != 0) {
+ rec->time -= 2082844800U;
+ wpt_tmp->SetCreationTime(rec->time);
+ }
+ track_add_wpt(trk_head, wpt_tmp);
+ }
+}
+
+static void
+coto_wpt_read(void)
+{
+ struct record_wpt* rec;
+ pdbrec_t* pdb_rec;
+ appinfo_t* app;
+ app = (struct appinfo*) file_in->appinfo;
+
+ for (pdb_rec = file_in->rec_list; pdb_rec; pdb_rec = pdb_rec->next) {
+ waypoint* wpt_tmp;
+ char* c;
+
+ wpt_tmp = waypt_new();
+
+ rec = (struct record_wpt*) pdb_rec->data;
+
+ wpt_tmp->longitude = DEG(-pdb_read_double(&rec->lon));
+ wpt_tmp->latitude = DEG(pdb_read_double(&rec->lat));
+
+ wpt_tmp->shortname = xstrndup(rec->name, sizeof(rec->name));
+
+ wpt_tmp->icon_descr = coto_get_icon_descr(pdb_rec->category, app);
+
+ if ((c = strstr(rec->notes, "\nNotes:\n"))) { /* remove our contruct */
+ wpt_tmp->notes = xstrdup(c + 8);
+ if (c != rec->notes) {
+ wpt_tmp->description = xstrndup(rec->notes, c - rec->notes);
+ }
+ } else {
+ wpt_tmp->notes = xstrdup(rec->notes);
+ }
+
+ waypt_add(wpt_tmp);
+ }
+}
+
+static void
+data_read(void)
+{
+ if ((file_in->creator != MYCREATOR) || ((file_in->type != MYTYPETRACK) && (file_in->type != MYTYPEWPT))) {
+ warning("Creator %x Type %x Version %d\n", (int) file_in->creator, (int) file_in->type, (int) file_in->version);
+ fatal(MYNAME ": Not a cotoGPS file.\n");
+ }
+
+ is_fatal((file_in->version > 0),
+ MYNAME ": This file is from an unsupported newer version of cotoGPS. It may be supported in a newer version of GPSBabel.\n");
+
+ switch (file_in->type) {
+ case MYTYPETRACK:
+ coto_track_read();
+ break;
+ case MYTYPEWPT:
+ coto_wpt_read();
+ break;
+ }
+}
+
+static void
+coto_prepare_wpt_write(void)
+{
+ struct appinfo* ai;
+
+ file_out->name[PDB_DBNAMELEN-1] = 0;
+ file_out->attr = PDB_FLAG_BACKUP;
+ file_out->type = MYTYPEWPT;
+ file_out->creator = MYCREATOR;
+ file_out->version = 0;
+
+ strncpy(file_out->name, "cotoGPS MarkerDB", PDB_DBNAMELEN);
+
+ file_out->appinfo_len = APPINFO_SIZE;
+ file_out->appinfo = calloc(APPINFO_SIZE,1);
+
+ ai = (struct appinfo*) file_out->appinfo;
+ be_write16(&ai->renamedCategories, 31); // Don't ask me why...
+ if (zerocat) {
+ strncpy(ai->categories[0], zerocat, 16);
+ } else {
+ strncpy(ai->categories[0], "Not Assigned", 16); // FIXME: Replace by default English Palm 'Not Assigned' category
+ }
+
+}
+
+static void
+coto_wpt_write(const waypoint* wpt)
+{
+ struct record_wpt* rec;
+ struct appinfo* ai = (struct appinfo*) file_out->appinfo;
+ char* notes = NULL;
+ char* shortname = NULL;
+ int size;
+ uint8_t cat = 0;
+ int i;
+
+ mkshort_wr_handle = mkshort_new_handle();
+ setshort_length(mkshort_wr_handle, MAX_MARKER_NAME_LENGTH);
+ setshort_whitespace_ok(mkshort_wr_handle, 1);
+
+ if ((global_opts.synthesize_shortnames && wpt->description) || (wpt->shortname == NULL)) {
+ shortname = mkshort_from_wpt(mkshort_wr_handle, wpt);
+ } else {
+ shortname = xstrdup(wpt->shortname);
+ }
+
+ if ((wpt->description) && ((strlen(wpt->description) > MAX_MARKER_NAME_LENGTH) || (strcmp(wpt->description, wpt->shortname)))) {
+ if ((wpt->notes) && (strcmp(wpt->description, wpt->notes) != 0)) {
+ notes = (char*) xcalloc(strlen(wpt->description) + strlen(wpt->notes) + 9, 1);
+ sprintf(notes, "%s\nNotes:\n%s", wpt->description, wpt->notes);
+ } else {
+ notes = xstrdup(wpt->description);
+ }
+ } else if (wpt->notes != NULL) {
+ notes = xstrdup(wpt->notes);
+ }
+
+ size = sizeof(*rec);
+ if (notes != NULL) {
+ size += strlen(notes);
+ }
+ rec = (struct record_wpt*) xcalloc(size, 1);
+
+ pdb_write_double(&rec->lon, RAD(-wpt->longitude));
+ pdb_write_double(&rec->lat, RAD(wpt->latitude));
+ strncpy(rec->name, shortname, MAX_MARKER_NAME_LENGTH);
+
+ if (notes) {
+ strcpy(rec->notes, notes);
+ xfree(notes);
+ }
+
+ if (!wpt->icon_descr.isNull()) {
+ for (i = 1; i < 16; i++)
+ if (!strncmp(wpt->icon_descr.toUtf8().data(), ai->categories[i], 16)) {
+ cat=i;
+ break;
+ }
+ if (!cat) {
+ // We have a new one
+ if (ai->maxid<15) {
+ i = ++ai->maxid;
+ snprintf(ai->categories[i], 16, "%s", wpt->icon_descr.toUtf8().data());
+ cat = ai->ids[i] = i;
+ } else {
+ // We're full!
+ warning(MYNAME ": Categories full. Category '%s' written as %s.\n", wpt->icon_descr.toUtf8().data(), zerocat?zerocat:"Not Assigned");
+ }
+ }
+ }
+
+ pdb_write_rec(file_out, 0, cat, ct++, (const uint8_t*)rec, size);
+
+ xfree(shortname);
+ xfree(rec);
+
+ mkshort_del_handle(&mkshort_wr_handle);
+}
+
+static void
+data_write(void)
+{
+ coto_prepare_wpt_write();
+ waypt_disp_all(coto_wpt_write);
+}
+
+
+ff_vecs_t coto_vecs = {
+ ff_type_file,
+ {(ff_cap)(ff_cap_read|ff_cap_write), ff_cap_read, ff_cap_none},
+ rd_init,
+ wr_init,
+ rd_deinit,
+ wr_deinit,
+ data_read,
+ data_write,
+ NULL,
+ coto_args,
+ CET_CHARSET_ASCII, 0 /* CET-REVIEW */
+};
+#endif
--- /dev/null
+/*
+ Read and write GeocachingPDB files.
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+#if PDBFMTS_ENABLED
+#include "pdbfile.h"
+
+#define MYNAME "GeocachingDB"
+#define MYTYPE 0x44415441 /* DATA */
+#define MYCREATOR 0x42726174 /* Brat */
+
+#define MAXRECSZ 500 /* This is overkill as the records seem to be around 100
+bytes a piece, but being conservative and dealing
+with realloc issues just doesn't seem worth it. */
+
+typedef enum {
+RECTYPE_TEXT = 0,
+RECTYPE_DATE = 2
+} gcdb_rectype;
+
+struct dbfld {
+char fldname[4];
+pdb_16 fldtype;
+pdb_16 fldlen;
+};
+
+struct dbrec {
+pdb_16 nflds;
+struct dbfld dbfld[1];
+};
+
+static pdbfile* file_in, *file_out;
+static const char* out_fname;
+static int ct;
+
+static char* tbuf = NULL;
+static char* tbufp = NULL;
+
+static void
+rd_init(const char* fname)
+{
+file_in = pdb_open(fname, MYNAME);
+}
+
+static void
+rd_deinit(void)
+{
+pdb_close(file_in);
+}
+
+static void
+wr_init(const char* fname)
+{
+file_out = pdb_create(fname, MYNAME);
+out_fname = fname;
+ct = 0;
+}
+
+static void
+wr_deinit(void)
+{
+pdb_close(file_out);
+if (tbuf) {
+xfree(tbuf);
+}
+}
+
+static void
+data_read(void)
+{
+pdbrec_t* pdb_rec;
+
+if ((file_in->creator != MYCREATOR) || (file_in->type != MYTYPE)) {
+fatal(MYNAME ": Not a GeocachingDB file.\n");
+}
+
+for (pdb_rec = file_in->rec_list; pdb_rec; pdb_rec=pdb_rec->next) {
+waypoint* wpt = waypt_new();
+struct dbrec* rec = (struct dbrec*) pdb_rec->data;
+int nflds;
+int length;
+int type;
+int i;
+char* recdata;
+int lat_dir = 0;
+int lat_deg = 0;
+float lat_min = 0.0;
+int lon_dir = 0;
+int lon_deg = 0;
+float lon_min = 0.0;
+
+nflds = be_read16(&rec->nflds);
+recdata = (char*) &rec->dbfld[nflds];
+
+for (i = 0; i < nflds; i++) {
+length = (unsigned short) be_read16(&rec->dbfld[i].fldlen);
+type = be_read16(&rec->dbfld[i].fldtype);
+
+switch (type) {
+case RECTYPE_TEXT: /* Text */
+if (!strncmp("gcid", rec->dbfld[i].fldname,4)) {
+wpt->shortname = xstrdup(recdata);
+} else if (!strncmp("gcna", rec->dbfld[i].fldname,4)) {
+wpt->description = xstrdup(recdata);
+} else if (!strncmp("lat0", rec->dbfld[i].fldname,4)) {
+lat_dir = *recdata == 'N' ? 1 : -1;
+} else if (!strncmp("lat1", rec->dbfld[i].fldname,4)) {
+lat_deg = atoi(recdata);
+} else if (!strncmp("lat2", rec->dbfld[i].fldname,4)) {
+lat_min = atof(recdata);
+}
+if (!strncmp("lon0", rec->dbfld[i].fldname,4)) {
+lon_dir = *recdata == 'E' ? 1 : -1;
+} else if (!strncmp("lon1", rec->dbfld[i].fldname,4)) {
+lon_deg = atoi(recdata);
+} else if (!strncmp("lon2", rec->dbfld[i].fldname,4)) {
+lon_min = atof(recdata);
+} else if (!strncmp("take", rec->dbfld[i].fldname,4)) {
+wpt->notes = xstrappend(wpt->notes, " Took ");
+wpt->notes = xstrappend(wpt->notes, recdata);
+} else if (!strncmp("left", rec->dbfld[i].fldname,4)) {
+wpt->notes = xstrappend(wpt->notes, " Left ");
+wpt->notes = xstrappend(wpt->notes, recdata);
+} else if (!strncmp("diff", rec->dbfld[i].fldname,4)) {
+waypt_alloc_gc_data(wpt)->diff = 10 * atof(recdata);
+} else if (!strncmp("terr", rec->dbfld[i].fldname,4)) {
+waypt_alloc_gc_data(wpt)->terr = 10 * atof(recdata);
+}
+break;
+#if 0
+/* This really is the date of the find,
+* not the cache creation date.
+*/
+case RECTYPE_DATE:
+if (!strncmp("date", rec->dbfld[i].fldname,4)) {
+time_t tm;
+tm = be_read32(recdata) * 24 * 3600;
+tm -= EPOCH_1904;
+wpt->SetCreationTime(tm);
+warning("date %d\n", tm);
+}
+break;
+#endif
+}
+recdata += (length + 1) & (~1);
+}
+wpt->latitude = lat_dir * (lat_deg + lat_min/60);
+wpt->longitude = lon_dir * (lon_deg + lon_min/60);
+waypt_add(wpt);
+}
+}
+
+
+static int
+gcdb_add_to_rec(struct dbrec* rec, const char* fldname, gcdb_rectype rectype, const void* data)
+{
+int length;
+static int rec_cnt;
+
+if (!tbuf) {
+tbuf = (char*) xcalloc(MAXRECSZ, 1);
+tbufp = tbuf;
+}
+
+if (fldname == NULL) {
+length = tbufp - tbuf;
+be_write16(&rec->nflds, rec_cnt);
+memcpy(&rec->dbfld[rec_cnt],tbuf, length);
+tbufp = tbuf;
+length += 4 + sizeof(struct dbfld) * rec_cnt;
+rec_cnt = 0;
+return length;
+}
+
+be_write16(&rec->dbfld[rec_cnt].fldtype,rectype);
+strncpy(rec->dbfld[rec_cnt].fldname, fldname, 4);
+
+switch (rectype) {
+case RECTYPE_TEXT:
+length = 1 + strlen((const char*)data);
+be_write16(&rec->dbfld[rec_cnt].fldlen, length);
+strcpy(tbufp, (const char*)data);
+tbufp += (length + 1) & (~1);
+break;
+case RECTYPE_DATE:
+length = 4;
+be_write16(&rec->dbfld[rec_cnt].fldlen, length);
+be_write32(tbufp, ((time_t)data - EPOCH_1904)/ (3600 * 24));
+tbufp += length;
+break;
+default:
+abort();
+}
+rec_cnt++;
+
+return length;
+}
+
+static void
+gcdb_write_wpt(const waypoint* wpt)
+{
+struct dbrec* rec;
+int reclen;
+char tbuf[100];
+
+/*
+* We don't really know how many fields we'll have or how long
+* they'll be so we'll just lazily create a huge place to hold them.
+*/
+rec = (struct dbrec*) xcalloc(sizeof(*rec) + 500, 1);
+
+gcdb_add_to_rec(rec, "gcna", RECTYPE_TEXT, wpt->description);
+gcdb_add_to_rec(rec, "gcid", RECTYPE_TEXT, wpt->shortname);
+
+gcdb_add_to_rec(rec, "lat0", RECTYPE_TEXT,
+wpt->latitude < 0 ? "S" : "N");
+
+sprintf(tbuf, "%d", (int) wpt->latitude);
+gcdb_add_to_rec(rec, "lat1", RECTYPE_TEXT, tbuf);
+
+sprintf(tbuf, "%f", 60 * (wpt->latitude -
+(int) wpt->latitude));
+gcdb_add_to_rec(rec, "lat2", RECTYPE_TEXT, tbuf);
+
+
+gcdb_add_to_rec(rec, "lon0", RECTYPE_TEXT,
+wpt->longitude < 0 ? "W" : "E");
+
+sprintf(tbuf, "%d", (int) wpt->longitude);
+gcdb_add_to_rec(rec, "lon1", RECTYPE_TEXT, tbuf);
+
+sprintf(tbuf, "%f", 60 * (wpt->longitude -
+(int) wpt->longitude));
+gcdb_add_to_rec(rec, "lon2", RECTYPE_TEXT, tbuf);
+
+if (wpt->gc_data->diff) {
+sprintf(tbuf, "%f", wpt->gc_data->diff / 10.0);
+gcdb_add_to_rec(rec, "diff", RECTYPE_TEXT, tbuf);
+}
+
+if (wpt->gc_data->terr) {
+sprintf(tbuf, "%f", wpt->gc_data->terr / 10.0);
+gcdb_add_to_rec(rec, "terr", RECTYPE_TEXT, tbuf);
+}
+
+#if 0
+/* This really is the date of the find,
+* not the cache creation date.
+*/
+if (wpt->creation_time) {
+gcdb_add_to_rec(rec, "date", RECTYPE_DATE, (void*) wpt->GetCreationTime());
+}
+#endif
+
+/*
+* We're done. Build the record.
+*/
+reclen = gcdb_add_to_rec(rec, NULL, (gcdb_rectype)0, NULL);
+
+pdb_write_rec(file_out, 0, 2, ct++, rec, reclen);
+xfree(rec);
+}
+
+static void
+data_write(void)
+{
+ strncpy(file_out->name, out_fname, PDB_DBNAMELEN);
+ strncpy(file_out->name, "GeocachingDB", PDB_DBNAMELEN);
+ file_out->name[PDB_DBNAMELEN-1] = 0;
+ file_out->attr = PDB_FLAG_BACKUP;
+ file_out->ctime = file_out->mtime = current_time().toTime_t() + 2082844800U;
+ file_out->type = MYTYPE; /* CWpt */
+ file_out->creator = MYCREATOR; /* cGPS */
+ file_out->version = 1;
+
+ waypt_disp_all(gcdb_write_wpt);
+}
+
+
+ff_vecs_t gcdb_vecs = {
+ ff_type_file,
+ FF_CAP_RW_WPT,
+ rd_init,
+ wr_init,
+ rd_deinit,
+ wr_deinit,
+ data_read,
+ data_write,
+ NULL,
+ NULL,
+ CET_CHARSET_ASCII, 0 /* CET-REVIEW */
+};
+#endif
--- /dev/null
+/*
+ Read and write GeoNiche files.
+
+ Copyright (C) 2003 Rick Richardson <rickr@mn.rr.com>
+ Copyright (C) 2006 Robert Lipe <robertlipe@usa.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+#if PDBFMTS_ENABLED
+#include "pdbfile.h"
+#include "jeeps/gpsmath.h"
+#include "garmin_tables.h"
+
+#include <math.h>
+#include <stdlib.h>
+
+#define MYNAME "Geoniche"
+#define MYTYPE_ASC 0x50454e44 /* PEND */
+#define MYTYPE_BIN 0x44415441 /* DATA */
+#define MYCREATOR 0x47656f4e /* GeoN */
+
+#undef GEONICHE_DBG
+
+static pdbfile* file_in, *file_out;
+static const char* FilenameOut;
+static int rec_ct;
+static int ct;
+static char Rec0Magic[] = "68000NV4Q2";
+
+static char* Arg_dbname = NULL;
+static char* Arg_category = NULL;
+
+static
+arglist_t Args[] = {
+ {
+ "dbname", &Arg_dbname,
+ "Database name (filename)", NULL, ARGTYPE_STRING, ARG_NOMINMAX
+ },
+ {
+ "category", &Arg_category,
+ "Category name (Cache)", NULL, ARGTYPE_STRING, ARG_NOMINMAX
+ },
+ ARG_TERMINATOR
+};
+
+#define ARG_FREE(X) do { if (X) { xfree(X); X = NULL; } } while (0)
+
+/*
+ * Conversions between gc.com ID's and GID's
+ */
+static char GcSet[] = "0123456789ABCDEFGHJKMNPQRTVWXYZ";
+static int GcOffset = 16 * 31 * 31 * 31 - 65536;
+
+static int
+gid2id(char* gid)
+{
+ char* p;
+ int i, val;
+
+ if (strncmp(gid, "GC", 2) != 0) {
+ return -1;
+ }
+ if (strlen(gid) != 6) {
+ return -1;
+ }
+ gid += 2;
+
+ if (strcmp(gid, "G000") < 0) {
+ return strtol(gid, NULL, 16);
+ }
+
+ for (val = i = 0; i < 4; ++i) {
+ val *= 31;
+ p = strchr(GcSet, gid[i]);
+ if (!p) {
+ return -1;
+ }
+ val += p - GcSet;
+ }
+ return val - GcOffset;
+}
+
+static void
+id2gid(char gid[6+1], int id)
+{
+ gid[0] = 0;
+ if (id < 0) {
+ return;
+ } else if (id < 65536) {
+ snprintf(gid, 6+1, "GC%04X", id);
+ } else {
+ int i;
+
+ id += GcOffset;
+ gid[0] = 'G';
+ gid[1] = 'C';
+ for (i = 5; i >= 2; --i) {
+ gid[i] = GcSet[id%31];
+ id /= 31;
+ }
+ gid[6] = 0;
+ if (id) {
+ gid[0] = 0;
+ }
+ }
+ return;
+}
+
+static void
+rd_init(const char* fname)
+{
+ file_in = pdb_open(fname, MYNAME);
+}
+
+static void
+rd_deinit(void)
+{
+ pdb_close(file_in);
+ ARG_FREE(Arg_dbname);
+ ARG_FREE(Arg_category);
+}
+
+static void
+wr_init(const char* fname)
+{
+ file_out = pdb_create(fname, MYNAME);
+ FilenameOut = fname;
+}
+
+static void
+wr_deinit(void)
+{
+ pdb_close(file_out);
+ ARG_FREE(Arg_dbname);
+ ARG_FREE(Arg_category);
+}
+
+static char*
+field(char** pp, int* lenp)
+{
+ int len = *lenp;
+ char* p = *pp;
+ char* dp, *dbuf;
+ int state = 0;
+
+ if (len == 0 || *p == 0) {
+ return NULL;
+ }
+
+ dbuf = dp = (char*) xmalloc(len);
+ while (len) {
+ char ch;
+
+ ch = *p++;
+ --len;
+ if (ch == 0 || len == 0) {
+ break;
+ }
+ switch (state) {
+ case 0:
+ if (ch == '\\') {
+ state = 1;
+ } else if (ch == ',') {
+ goto eof;
+ } else {
+ *dp++ = ch;
+ }
+ break;
+ default:
+ *dp++ = ch;
+ state = 0;
+ break;
+ }
+ }
+eof:
+ *dp++ = 0;
+ dbuf = (char*) xrealloc(dbuf, dp - dbuf);
+ /* fprintf(stderr, "<%.8s> dbuf=%x, len=%d\n", *pp, dbuf, len); */
+ *pp = p;
+ *lenp = len;
+ return dbuf;
+}
+
+static void
+geoniche_read_asc(void)
+{
+ pdbrec_t* pdb_rec;
+
+ /* Process record 0 */
+ pdb_rec = file_in->rec_list;
+ if (!pdb_rec || strcmp((char*) pdb_rec->data, Rec0Magic)) {
+ fatal(MYNAME ": Bad record 0, not a GeoNiche file.\n");
+ }
+ pdb_rec = pdb_rec->next;
+
+ /* Process the rest of the records */
+ for (; pdb_rec; pdb_rec = pdb_rec->next) {
+ waypoint* wpt;
+ char* vdata;
+ int vlen;
+ char* p;
+
+ int id;
+ int route_id;
+ char* title;
+ QString category;
+ double lat, lon, alt;
+ char* datestr, *timestr;
+ int icon;
+ char* notes;
+ char gid[6+1];
+ struct tm tm;
+
+ memset(&tm, 0, sizeof(tm));
+
+ wpt = waypt_new();
+ if (!wpt) {
+ fatal(MYNAME ": Couldn't allocate waypoint.\n");
+ }
+ vdata = (char*) pdb_rec->data;
+ vlen = pdb_rec->size;
+
+ /* Field 1: Target */
+ p = field(&vdata, &vlen);
+ if (!p) {
+ fatal(MYNAME ": Premature EOD processing field 1 (target).\n");
+ }
+ if (strcmp(p, "Route") == 0) {
+ fatal(MYNAME ": Route record type is not implemented.\n");
+ }
+ if (strcmp(p, "Target")) {
+ fatal(MYNAME ": Unknown record type '%s'.\n", p);
+ }
+ xfree(p);
+
+ /* Field 2: Import ID number */
+ p = field(&vdata, &vlen);
+ if (!p) {
+ fatal(MYNAME ": Premature EOD processing field 2 (ID).\n");
+ }
+ id = atoi(p);
+ xfree(p);
+
+ /* Field 3: Title */
+ p = field(&vdata, &vlen);
+ if (!p) {
+ fatal(MYNAME ": Premature EOD processing field 3 (Title).\n");
+ }
+ title = p;
+
+ /* Field 4: Route ID number */
+ p = field(&vdata, &vlen);
+ if (!p) {
+ fatal(MYNAME ": Premature EOD processing field 4 (Route ID).\n");
+ }
+ route_id = atoi(p);
+ xfree(p);
+
+ /* Field 5: Category */
+ p = field(&vdata, &vlen);
+ if (!p) {
+ fatal(MYNAME ": Premature EOD processing field 5 (Category).\n");
+ }
+ category = p;
+ xfree(p);
+
+ /* Field 6: Latitude */
+ p = field(&vdata, &vlen);
+ if (!p) {
+ fatal(MYNAME ": Premature EOD processing field 6 (Latitude).\n");
+ }
+ lat = atof(p);
+ xfree(p);
+
+ /* Field 7: Longitude */
+ p = field(&vdata, &vlen);
+ if (!p) {
+ fatal(MYNAME ": Premature EOD processing field 7 (Longitude).\n");
+ }
+ lon = atof(p);
+ xfree(p);
+
+ /* Field 8: Altitude */
+ p = field(&vdata, &vlen);
+ if (!p) {
+ fatal(MYNAME ": Premature EOD processing field 8 (Altitude).\n");
+ }
+ alt = atof(p);
+ xfree(p);
+
+ /* Field 9: Creation date */
+ p = field(&vdata, &vlen);
+ if (!p) {
+ fatal(MYNAME ": Premature EOD processing field 9 (Creation date).\n");
+ }
+ datestr = p;
+
+ /* Field 10: Creation time */
+ p = field(&vdata, &vlen);
+ if (!p) {
+ fatal(MYNAME ": Premature EOD processing field 10 (Creation time).\n");
+ }
+ timestr = p;
+
+ /* Field 11: Visited date */
+ p = field(&vdata, &vlen);
+ if (!p) {
+ fatal(MYNAME ": Premature EOD processing field 11 (Visited date).\n");
+ }
+ xfree(p);
+
+ /* Field 12: Visited time */
+ p = field(&vdata, &vlen);
+ if (!p) {
+ fatal(MYNAME ": Premature EOD processing field 12 (Visited time).\n");
+ }
+ xfree(p);
+
+ /* Field 13: Icon color (R G B) */
+ p = field(&vdata, &vlen);
+ if (!p) {
+ fatal(MYNAME ": Premature EOD processing field 13 (Icon color).\n");
+ }
+ xfree(p);
+
+ /* Field 14: icon number */
+ p = field(&vdata, &vlen);
+ if (!p) {
+ fatal(MYNAME ": Premature EOD processing field 14 (Icon number).\n");
+ }
+ icon = atoi(p);
+ xfree(p);
+
+ /* Field 15: unused */
+ p = field(&vdata, &vlen);
+ if (!p) {
+ fatal(MYNAME ": Premature EOD processing field 15 (unused1).\n");
+ }
+ xfree(p);
+
+ /* Field 16: unused */
+ p = field(&vdata, &vlen);
+ if (!p) {
+ fatal(MYNAME ": Premature EOD processing field 16 (unused2).\n");
+ }
+ xfree(p);
+
+ /* Field 17: unused */
+ p = field(&vdata, &vlen);
+ if (!p) {
+ fatal(MYNAME ": Premature EOD processing field 17 (unused3).\n");
+ }
+ xfree(p);
+
+ /* Field 18: Notes */
+ p = field(&vdata, &vlen);
+ if (!p) {
+ fatal(MYNAME ": Premature EOD processing field 18 (Notes).\n");
+ }
+ notes = p;
+
+ sscanf(datestr, "%d/%d/%d", &tm.tm_mon, &tm.tm_mday, &tm.tm_year);
+ tm.tm_mon -= 1;
+ tm.tm_year -= 1900;
+ sscanf(timestr, "%d:%d:%d", &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
+ if (tm.tm_year >= 1970) {
+ wpt->SetCreationTime(mktime(&tm));
+ }
+ xfree(datestr);
+ xfree(timestr);
+
+ id2gid(gid, id);
+ wpt->latitude = lat;
+ wpt->longitude = lon;
+ wpt->altitude = alt;
+ wpt->icon_descr = category;
+
+ if (gid[0]) {
+ wpt->shortname = xstrdup(gid);
+ wpt->description = title;
+ wpt->notes = notes;
+ } else {
+ wpt->shortname = xstrdup(title);
+ wpt->description = title;
+ wpt->notes = notes;
+ }
+
+ waypt_add(wpt);
+ }
+}
+
+static const char* geoniche_icon_map[] = /* MPS */
+{
+ /* 21 */ "Cross",
+ /* 22 */ "Cross (light)",
+ /* 23 */ "Cross (little)",
+ /* 24 */ "Cross (straight)",
+ /* 25 */ "Cross (light straight)",
+ /* 26 */ "Cross (little straight)",
+ /* 27 */ NULL,
+ /* 28 */ NULL,
+ /* 29 */ NULL,
+ /* 2A */ "Flag",
+ /* 2B */ "Car", /* 56 */
+ /* 2C */ "Gas Station", /* 8 */
+ /* 2D */ "Observation Point",
+ /* 2E */ "Scenic Area", /* 48 */
+ /* 2F */ "City",
+ /* 30 */ "Mountains",
+ /* 31 */ "Park", /* 46 */
+ /* 32 */ "Forest", /* 105 */
+ /* 33 */ "Campground", /* 38 */
+ /* 34 */ NULL,
+ /* 35 */ "Men",
+ /* 36 */ "Woman",
+ /* 37 */ "Hotel", /* 59 */
+ /* 38 */ "Residence", /* 10 */
+ /* 39 */ "Restaurant", /* 11 */
+ /* 3A */ "Cafe",
+ /* 3B */ NULL,
+ /* 3C */ "Airport", /* 107 */
+ /* 3D */ "Medical Facility", /* 43 */
+ /* 3E */ "Ropeway",
+ /* 3F */ "Sailing Area",
+ /* 40 */ "Anchor",
+ /* 41 */ NULL, /* Half Anchor ??? */
+ /* 42 */ "Fishing Area", /* 7 */
+ /* 43 */ "Stop Sign",
+ /* 44 */ "Question Sign",
+ /* 45 */ NULL,
+ /* 46 */ NULL,
+ /* 47 */ "Euro Sign",
+ /* 48 */ "Bank", /* 6 */
+ /* 49 */ NULL,
+ /* 4A */ "Left Arrow",
+ /* 4B */ "Right Arrow",
+ /* 4C */ "Traditional Cache",
+ /* 4D */ "Multi-Cache", /* 86 */
+ /* 4E */ "Virtual Cache", /* 48 */
+ /* 4F */ "Letterbox Cache",
+ /* 50 */ "Event Cache", /* 47 */
+ /* 51 */ "Webcam Cache", /* 90 */
+ /* 52 */ "Mystery or puzzle Cache",
+};
+
+static const QString
+geoniche_icon_to_descr(const int no)
+{
+ const char* result = NULL;
+
+ if (no >= 0x21) {
+ int i = no - 0x21;
+ if (i <= 49) {
+ result = geoniche_icon_map[i];
+ }
+ }
+ return result;
+}
+
+static void
+geoniche_read_bin(void)
+{
+ pdbrec_t* pdb_rec;
+
+ /* Process records */
+
+ for (pdb_rec = file_in->rec_list; pdb_rec != NULL; pdb_rec = pdb_rec->next) {
+ char* vdata = (char*) pdb_rec->data;
+ struct tm created, visited;
+ int icon_nr, selected;
+ int latdeg, londeg;
+ double lat, lon, altitude;
+ waypoint* waypt;
+
+ memset(&visited, 0, sizeof(visited));
+ memset(&created, 0, sizeof(created));
+
+ latdeg = be_read16(vdata + 0);
+ lat = be_read32(vdata + 2);
+ londeg = be_read16(vdata + 6);
+ lon = be_read32(vdata + 8);
+ altitude = (float) be_read32(vdata + 12);
+ selected = vdata[16];
+ created.tm_min = be_read16(vdata + 20);
+ created.tm_hour = be_read16(vdata + 22);
+ created.tm_mday = be_read16(vdata + 24);
+ created.tm_mon = be_read16(vdata + 26);
+ created.tm_year = be_read16(vdata + 28);
+ visited.tm_min = be_read16(vdata + 34);
+ visited.tm_hour = be_read16(vdata + 36);
+ visited.tm_mday = be_read16(vdata + 38);
+ visited.tm_mon = be_read16(vdata + 40);
+ visited.tm_year = be_read16(vdata + 42);
+
+#ifdef GEONICHE_DBG
+ printf(MYNAME "-date: %04d/%02d/%02d, %02d:%02d (%04d/%02d/%02d, %02d:%02d)\n",
+ created.tm_year, created.tm_mon, created.tm_mday, created.tm_hour, created.tm_min,
+ visited.tm_year, visited.tm_mon, visited.tm_mday, visited.tm_hour, visited.tm_min);
+#endif
+ icon_nr = vdata[62];
+
+ latdeg = 89 - latdeg;
+ lat = lat * (double) 0.0000006;
+ if (latdeg >= 0) {
+ lat = (double) 60.0 - lat;
+ } else {
+ latdeg++;
+ }
+
+ lon = lon * (double) 0.0000006;
+ while (londeg >= 360) {
+ londeg-=360;
+ }
+ if (londeg > 180) {
+ lon = (double) 60.0 - lon;
+ londeg = londeg - 359;
+ }
+
+ created.tm_year-=1900;
+ created.tm_mon--;
+
+ waypt = waypt_new();
+
+ waypt->shortname = xstrdup(vdata + 63);
+ waypt->altitude = altitude;
+ waypt->SetCreationTime(mkgmtime(&created));
+
+ GPS_Math_DegMin_To_Deg(latdeg, lat, &waypt->latitude);
+ GPS_Math_DegMin_To_Deg(londeg, lon, &waypt->longitude);
+
+ waypt->icon_descr = geoniche_icon_to_descr(icon_nr);
+ waypt_add(waypt);
+ }
+}
+
+static void
+data_read(void)
+{
+ if (file_in->creator != MYCREATOR) {
+ fatal(MYNAME ": Not a GeoNiche file.\n");
+ }
+
+ switch (file_in->type) {
+ case MYTYPE_ASC:
+ geoniche_read_asc();
+ break;
+ case MYTYPE_BIN:
+ geoniche_read_bin();
+ break;
+ default:
+ fatal(MYNAME ": Unsupported GeoNiche file.\n");
+ }
+}
+
+static char*
+enscape(char* s)
+{
+ char* buf, *d;
+
+ if (!s) {
+ d = (char*) xmalloc(1);
+ *d = 0;
+ return d;
+ }
+ buf = d = (char*) xmalloc(strlen(s) * 2 + 1);
+ for (; *s; ++s) {
+
+ /*
+ * 3 May 06: need to escape single quotes for v1.40 release
+ */
+
+ if (*s == '\\' || *s == ',' || *s == '\'') {
+ *d++ = '\\';
+ *d++ = *s;
+ }
+
+ /* 3 May 06: stop stripping for better readability
+ *
+ * else if ((*s == '\r') || (*s == '\n'))
+ * *d++ = ' ';
+ */
+ else {
+ *d++ = *s;
+ }
+ }
+
+ *d = 0;
+ return buf;
+}
+
+/*
+ * Attempt to map an icon description into a GeoNiche icon number
+ */
+static int
+wpt2icon(const waypoint* wpt)
+{
+ QString desc = wpt->icon_descr;
+
+ if (desc.isNull()) {
+ return 0;
+ } else if (desc.contains("reg")) {
+ return 43;
+ } else if (desc.contains("trad")) {
+ return 43;
+ } else if (desc.contains("multi")) {
+ return 44;
+ } else if (desc.contains("offset")) {
+ return 44;
+ } else if (desc.contains("virt")) {
+ return 45;
+ } else if (desc.contains("loca")) {
+ return 45;
+ } else if (desc.contains("event")) {
+ return 46;
+ } else if (desc.contains("lett")) {
+ return 47;
+ } else if (desc.contains("hyb")) {
+ return 47;
+ } else if (desc.contains("unk")) {
+ return 48;
+ } else if (desc.contains("cam")) {
+ return 49;
+ }
+
+ switch (wpt->gc_data->type) {
+ case gt_traditional:
+ return 43;
+ case gt_multi:
+ return 44;
+ case gt_locationless:
+ return 45;
+ case gt_earth:
+ return 45;
+ case gt_virtual:
+ return 45;
+ case gt_letterbox:
+ return 46;
+ case gt_event:
+ return 47;
+ case gt_cito:
+ return 47;
+ case gt_suprise:
+ return 48;
+ case gt_webcam:
+ return 49;
+ case gt_unknown:
+ return 0;
+ case gt_benchmark:
+ return 0;
+ case gt_ape:
+ return 0;
+ case gt_mega:
+ return 0;
+ case gt_wherigo:
+ return 0;
+ }
+
+ return 0;
+}
+
+static char*
+geoniche_geostuff(const waypoint* wpt)
+{
+ char* gs = NULL, *tmp1, *tmp2, *tmp3;
+ char tbuf[10240];
+
+ if (!wpt->gc_data->terr) {
+ return NULL;
+ }
+
+ snprintf(tbuf, sizeof(tbuf), "\n%s by %s\n\n", gs_get_cachetype(wpt->gc_data->type), wpt->gc_data->placer.toUtf8().data());
+ gs = xstrappend(gs, tbuf);
+
+ /*
+ * 3 May 06: Removed duplicated information
+ *
+ * snprintf(tbuf, sizeof(tbuf), "Waypoint: %s %s\n", wpt->shortname, wpt->description);
+ * gs = xstrappend(gs, tbuf);
+ */
+
+ /*
+ * 3 May 06: Added container type
+ */
+ snprintf(tbuf, sizeof(tbuf), "Container: %s\nDifficulty: %3.1f\nTerrain: %3.1f\n\n", gs_get_container(wpt->gc_data->container), wpt->gc_data->diff/10.0, wpt->gc_data->terr/10.0);
+ gs = xstrappend(gs, tbuf);
+
+ tmp1 = strip_html(&wpt->gc_data->desc_short);
+ tmp2 = strip_html(&wpt->gc_data->desc_long);
+ gs = xstrappend(gs, tmp1);
+ gs = xstrappend(gs, tmp2);
+
+ tmp3 = rot13(wpt->gc_data->hint);
+ snprintf(tbuf, sizeof(tbuf), "\n\nHint: %s\n", tmp3);
+ gs = xstrappend(gs, tbuf);
+
+ xfree(tmp1);
+ xfree(tmp2);
+ xfree(tmp3);
+
+ tmp1 = enscape(gs);
+ xfree(gs);
+
+ return tmp1;
+}
+
+static void
+geoniche_writewpt(const waypoint* wpt)
+{
+ int vlen;
+ char* vdata;
+ char* title;
+ struct tm tm;
+ char datestr[10+1];
+ char timestr[8+1];
+ char* notes;
+ int id;
+ time_t tx;
+ char* gs;
+
+ if (rec_ct == 0) {
+ pdb_write_rec(file_out, 0, 0, ct++, Rec0Magic, sizeof(Rec0Magic));
+ }
+
+ if (wpt->description && wpt->description[0]) {
+ title = enscape(wpt->description);
+ } else {
+ title = enscape(wpt->shortname);
+ }
+
+ id = gid2id(wpt->shortname);
+ if (id < 0) {
+ id = rec_ct;
+ }
+
+ if (wpt->GetCreationTime().isValid()) {
+ tx = wpt->GetCreationTime().toTime_t();
+ } else {
+ tx = gpsbabel_time;
+ }
+ if (tx == 0) { /* maybe zero during testo (freezed time) */
+ strcpy(datestr, "01/01/1904"); /* this seems to be the uninitialized date value for geoniche */
+ strcpy(timestr, "00:00:00");
+ } else {
+ tm = *localtime(&tx);
+ strftime(datestr, sizeof(datestr), "%m/%d/%Y", &tm);
+ strftime(timestr, sizeof(timestr), "%H:%M:%S", &tm);
+ }
+
+ /* Notes field MUST have soemthing in it */
+ if (!wpt->notes || wpt->notes[0] == 0) {
+ notes = xstrdup(title);
+ } else {
+ notes = enscape(wpt->notes);
+ }
+
+ gs = geoniche_geostuff(wpt);
+ if (gs) {
+ notes = xstrappend(notes, gs);
+ xfree(gs);
+ }
+ /* last chance to fill notes with something */
+ if (*notes == '\0') {
+ notes = xstrappend(notes, "(notes)");
+ }
+
+ vlen = xasprintf(&vdata,
+ "Target,%d,%s,,%s,%f,%f,%f,%s,%s,,,,%d,,,,%s"
+ , id
+ , title
+ /* route ID */
+ , Arg_category ? Arg_category : "Cache"
+ , wpt->latitude
+ , wpt->longitude
+ , wpt->altitude
+ , datestr
+ , timestr
+ /* visited date */
+ /* visited time */
+ /* icon color R G B */
+ , wpt2icon(wpt)
+ /* unused1 */
+ /* unused2 */
+ /* unused3 */
+ , notes
+ );
+
+ pdb_write_rec(file_out, 0, 0, ct++, vdata, vlen + 1);
+
+ xfree(notes);
+ xfree(title);
+ xfree(vdata);
+
+ rec_ct++;
+}
+
+static void
+data_write(void)
+{
+ if (Arg_dbname) {
+ if (case_ignore_strcmp(Arg_dbname, "GeoNiche Targets") == 0) {
+ fatal(MYNAME ": Reserved database name!\n");
+ }
+ strncpy(file_out->name, Arg_dbname, PDB_DBNAMELEN);
+ } else {
+ strncpy(file_out->name, FilenameOut, PDB_DBNAMELEN);
+ }
+ file_out->name[PDB_DBNAMELEN-1] = 0;
+
+ file_out->attr = PDB_FLAG_BACKUP;
+ file_out->ctime = file_out->mtime = current_time().toTime_t() + (49*365 + 17*366) * (60*60*24);
+ file_out->type = MYTYPE_ASC;
+ file_out->creator = MYCREATOR;
+ file_out->version = 0;
+ file_out->revision = 1;
+
+ rec_ct = 0;
+ ct = 0;
+ waypt_disp_all(geoniche_writewpt);
+}
+
+
+ff_vecs_t geoniche_vecs = {
+ ff_type_file,
+ FF_CAP_RW_WPT,
+ rd_init,
+ wr_init,
+ rd_deinit,
+ wr_deinit,
+ data_read,
+ data_write,
+ NULL,
+ Args,
+ CET_CHARSET_MS_ANSI, 0 /* CET-REVIEW */
+};
+#endif
--- /dev/null
+/*
+ Read and write GPilotS files.
+
+ Copyright (C) 2003 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+#if PDBFMTS_ENABLED
+#include "pdbfile.h"
+#include "garmin_tables.h"
+
+#define MYNAME "GPilotS"
+#define MYWPT 0x57707473 /* Wpts */
+#define MYTRK 0x54726b73 /* Trks */
+#define MYRTE 0x57707473 /* Wpts */
+#define MYCREATOR 0x4750696c /* GPil */
+
+
+/*
+ * Structures grafted from http://www.cru.fr/perso/cc/GPilotS/
+ */
+
+
+typedef struct {
+ long lat; /* latitude in semicircles */
+ long lon; /* longitude in semicircles */
+}
+Semicircle_Type;
+
+typedef struct {
+ char ident[6]; /* identifier */
+ unsigned char lat[4]; /* position */
+ unsigned char lon[4]; /* position */
+ unsigned char unused[4]; /* should be set to zero */
+ char cmnt[40]; /* comment */
+ unsigned char smbl; /* symbol id */
+ unsigned char dspl; /* display option */
+} D103_Wpt_Type;
+
+typedef union {
+ float f;
+ unsigned int i;
+} fi_t;
+
+typedef struct { /* size */
+ unsigned char wpt_class; /* class (see below) 1 */
+ unsigned char color; /* color (see below) 1 */
+ unsigned char dspl; /* display options (see below) 1 */
+ unsigned char attr; /* attributes (see below) 1 */
+ unsigned char smbl[2]; /* waypoint symbol 2 */
+ unsigned char subclass[18]; /* subclass 18 */
+ unsigned char lat[4]; /* position */
+ unsigned char lon[4]; /* position */
+ float alt; /* altitude in meters 4 */
+ float dpth; /* depth in meters 4 */
+ float dist; /* proximity distance in meters 4 */
+ char state[2]; /* state 2 */
+ char cc[2]; /* country code 2 */
+ char varlenstrs[1]; /* start of variable length strings */
+ /* G_char ident[]; variable length string 1-51 */
+ /* G_char comment[]; waypoint user comment 1-51 */
+ /* G_char facility[]; facility name 1-31 */
+ /* G_char city[]; city name 1-25 */
+ /* G_char addr[]; address number 1-51 */
+ /* G_char cross_road[]; intersecting road label 1-51 */
+}
+D108_Wpt_Type;
+
+typedef struct { /* structure de waypoint "interne" */
+ unsigned char ident[51]; /* identifier (50 + '0') */
+ Semicircle_Type posn; /* position (common to all Garmin types) */
+ unsigned char cmnt[51]; /* comment (50 + '0') */
+ float dst; /* proximity distance */
+ float alt; /* altitude */
+ int smbl; /* symbol id */
+ unsigned char dspl; /* display option */
+ unsigned char color; /* color */
+}
+Custom_Wpt_Type;
+
+typedef struct { /* internal track header */
+ char name[256]; /* nom du groupe de trackpoints */
+ unsigned char dspl; /* display on the map ? */
+ unsigned char color; /* color */
+ unsigned char type; /* type of following track points */
+ unsigned char unused; /* type of following track points */
+ unsigned char number[2]; /* number of track points */
+ unsigned char latmin[4]; /* latitude min */
+ unsigned char latmax[4]; /* latitude max */
+ unsigned char lonmin[4]; /* longitude min */
+ unsigned char lonmax[4]; /* longitude max */
+ unsigned char unused2[2]; /* type of following track points */
+}
+Custom_Trk_Hdr_Type;
+
+typedef struct {
+ unsigned char lat[4]; /* position */
+ unsigned char lon[4]; /* position */
+ unsigned char time[4];
+ unsigned char alt[4];
+ unsigned char new_trk;
+ unsigned char unused;
+} Custom_Trk_Point_Type;
+
+typedef struct { /* custom compact track point type */
+ unsigned char lat[4]; /* position */
+ unsigned char lon[4]; /* position */
+ unsigned char new_trk;
+ unsigned char unused;
+} Compact_Trk_Point_Type; /* size : 10 bytes */
+
+struct record {
+ struct {
+ unsigned char type;
+ unsigned short size;
+ unsigned int version;
+ } header;
+ union {
+ D103_Wpt_Type d103;
+ D108_Wpt_Type d108;
+ Custom_Wpt_Type CustWpt;
+ Custom_Trk_Hdr_Type CustTrkHdr;
+#if LATER
+ Custom_Rte_Hdr_Type CustRteHdr;
+#endif
+ } wpt;
+};
+
+
+static pdbfile* file_in, *file_out;
+static const char* out_fname;
+static int ct = 0;
+static char* dbname = NULL;
+
+static
+arglist_t my_args[] = {
+ {"dbname", &dbname, "Database name", NULL, ARGTYPE_STRING, ARG_NOMINMAX},
+ ARG_TERMINATOR
+};
+
+static void
+rd_init(const char* fname)
+{
+ file_in = pdb_open(fname, MYNAME);
+}
+
+static void
+rd_deinit(void)
+{
+ pdb_close(file_in);
+ if (dbname) {
+ xfree(dbname);
+ dbname = NULL;
+ }
+}
+
+static void
+wr_init(const char* fname)
+{
+ file_out = pdb_create(fname, MYNAME);
+ out_fname = fname;
+}
+
+static void
+wr_deinit(void)
+{
+ pdb_close(file_out);
+ if (dbname) {
+ xfree(dbname);
+ dbname = NULL;
+ }
+}
+
+static void
+data_read(void)
+{
+ struct record* rec;
+ pdbrec_t* pdb_rec;
+ route_head* track_head = NULL;
+
+ if (file_in->creator != MYCREATOR) {
+ fatal(MYNAME ": Not a %s file.\n", MYNAME);
+ }
+
+ switch (file_in->type) {
+ case MYWPT:
+ /* blah */
+ break;
+ case MYTRK:
+ /* blah */
+ break;
+ default:
+ fatal(MYNAME ": Unknown file type 0x%x\n", (int) file_in->type);
+ }
+
+ for (pdb_rec = file_in->rec_list; pdb_rec; pdb_rec=pdb_rec->next) {
+ waypoint* wpt_tmp;
+ Custom_Trk_Point_Type* tp_cust;
+ Compact_Trk_Point_Type* tp_comp;
+ int lat;
+ int lon;
+ int sz;
+ fi_t fi;
+ int trk_num = 0;
+ int trk_seg_num = 1;
+ char trk_seg_num_buf[10];
+ const char* trk_name = "";
+
+ wpt_tmp = waypt_new();
+
+ rec = (struct record*) pdb_rec->data;
+ switch (rec->header.type) {
+ /*
+ * G103Type
+ */
+ case 4:
+ wpt_tmp->shortname = xstrndupt(rec->wpt.d103.ident, sizeof(rec->wpt.d103.ident));
+ wpt_tmp->description = xstrndupt(rec->wpt.d103.cmnt, sizeof(rec->wpt.d103.cmnt));
+ /* This is odd. This is a Palm DB file,
+ * yet the data appears to be little endian,
+ * not appropriate the the actual Palm.
+ */
+ lon = le_read32(&rec->wpt.d103.lon);
+ lat = le_read32(&rec->wpt.d103.lat);
+ wpt_tmp->longitude = lon / 2147483648.0 * 180.0;
+ wpt_tmp->latitude = lat / 2147483648.0 * 180.0;
+ waypt_add(wpt_tmp);
+ break;
+ /*
+ * G108Type
+ */
+ case 9:
+ wpt_tmp->shortname = xstrndupt(rec->wpt.d108.varlenstrs, 50);
+ wpt_tmp->description = xstrndupt(rec->wpt.d108.varlenstrs + strlen(wpt_tmp->shortname) + 1, 50);
+ /* This is odd. This is a Palm DB file,
+ * yet the data appears to be little endian,
+ * not appropriate the the actual Palm.
+ */
+ lon = le_read32(&rec->wpt.d108.lon);
+ lat = le_read32(&rec->wpt.d108.lat);
+ wpt_tmp->longitude = lon / 2147483648.0 * 180.0;
+ wpt_tmp->latitude = lat / 2147483648.0 * 180.0;
+ fi.i = le_read32(&rec->wpt.d108.alt);
+ wpt_tmp->altitude = fi.f;
+ fi.i = le_read32(&rec->wpt.d108.dpth);
+ WAYPT_SET(wpt_tmp, depth, fi.f);
+ fi.i = le_read32(&rec->wpt.d108.dist);
+ WAYPT_SET(wpt_tmp, proximity, fi.f);
+ wpt_tmp->icon_descr = gt_find_desc_from_icon_number((rec->wpt.d108.smbl[1] << 8) + rec->wpt.d108.smbl[0], PCX, NULL);
+ waypt_add(wpt_tmp);
+ break;
+
+ /*
+ * CustomTrkHdr
+ */
+ case 101:
+ trk_name = rec->wpt.CustTrkHdr.name;
+ sz = be_read16(&rec->wpt.CustTrkHdr.number);
+
+ /* switch between custom track points and compact track points.
+ * (compact points have no altitude and time info.
+ */
+ switch (rec->wpt.CustTrkHdr.type) {
+ case 102:
+ tp_cust = (Custom_Trk_Point_Type*)((char*) pdb_rec->data + sizeof(rec->header) + sizeof(rec->wpt.CustTrkHdr));
+ while (sz--) {
+ if ((int)(tp_cust->new_trk) == 1 || trk_seg_num == 1) {
+ /*
+ * Start a new track segment
+ */
+ track_head = route_head_alloc();
+ if (trk_seg_num == 1) {
+ track_head->rte_name = xstrdup(trk_name);
+ } else {
+ /* name in the form TRACKNAME #n */
+ snprintf(trk_seg_num_buf, sizeof(trk_seg_num_buf), "%d", trk_seg_num);
+ track_head->rte_name = (char*) xmalloc(strlen(trk_name)+strlen(trk_seg_num_buf)+3);
+ sprintf(track_head->rte_name, "%s #%s", trk_name, trk_seg_num_buf);
+ }
+ trk_seg_num++;
+ track_head->rte_num = trk_num;
+ trk_num++;
+ track_add_head(track_head);
+ }
+
+ wpt_tmp = waypt_new();
+
+ /* This is even more odd.
+ * Track data is stored as big endian while
+ * waypoint data is little endian!?
+ */
+ lon = be_read32(&tp_cust->lon);
+ lat = be_read32(&tp_cust->lat);
+ wpt_tmp->longitude = lon / 2147483648.0 * 180.0;
+ wpt_tmp->latitude = lat / 2147483648.0 * 180.0;
+ /*
+ * Convert Garmin/GPilotS time format to gpsbabel time format.
+ * Garmin/GPilotS count seconds from "UTC 12:00 AM December 31 1989".
+ * gpsbabel counts seconds from "UTC 12:00 AM January 1 1970".
+ */
+ wpt_tmp->SetCreationTime(be_read32(&tp_cust->time) + 631065600);
+ fi.i = be_read32(&tp_cust->alt);
+ wpt_tmp->altitude = fi.f;
+ track_add_wpt(track_head, wpt_tmp);
+ tp_cust++;
+ }
+ break;
+ case 104:
+ tp_comp = (Compact_Trk_Point_Type*)((char*) pdb_rec->data + sizeof(rec->header) + sizeof(rec->wpt.CustTrkHdr));
+ while (sz--) {
+ if ((int)(tp_comp->new_trk) == 1 || trk_seg_num == 1) {
+ /*
+ * Start a new track segment
+ */
+ track_head = route_head_alloc();
+ if (trk_seg_num == 1) {
+ track_head->rte_name = xstrdup(trk_name);
+ } else {
+ /* name in the form TRACKNAME #n */
+ snprintf(trk_seg_num_buf, sizeof(trk_seg_num_buf), "%d", trk_seg_num);
+ track_head->rte_name = (char*) xmalloc(strlen(trk_name)+strlen(trk_seg_num_buf)+3);
+ sprintf(track_head->rte_name, "%s #%s", trk_name, trk_seg_num_buf);
+ }
+ trk_seg_num++;
+ track_head->rte_num = trk_num;
+ trk_num++;
+ track_add_head(track_head);
+ }
+
+ wpt_tmp = waypt_new();
+ lon = be_read32(&tp_comp->lon);
+ lat = be_read32(&tp_comp->lat);
+ wpt_tmp->longitude = lon / 2147483648.0 * 180.0;
+ wpt_tmp->latitude = lat / 2147483648.0 * 180.0;
+ track_add_wpt(track_head, wpt_tmp);
+ tp_comp++;
+ }
+ break;
+ default:
+ fatal(MYNAME ": track point type %d not supported.\n", rec->wpt.CustTrkHdr.type);
+ }
+ break;
+ default:
+ fatal(MYNAME ": input record type %d not supported.\n", rec->header.type);
+ }
+
+ }
+}
+
+
+struct hdr {
+ char* wpt_name;
+ waypoint* wpt;
+};
+
+static void
+my_write_wpt(const waypoint* wpt)
+{
+ struct record* rec;
+ char* vdata;
+ int lat, lon;
+
+ rec = (struct record*) xcalloc(sizeof *rec, 1);
+ vdata = (char*)rec + sizeof(*rec);
+
+ rec->header.type = 4;
+ rec->header.size = 5;
+ rec->header.version = 6;
+
+ strncpy(rec->wpt.d103.ident, wpt->shortname, sizeof(rec->wpt.d103.ident));
+ strncpy(rec->wpt.d103.cmnt, wpt->description, sizeof(rec->wpt.d103.cmnt));
+ lat = wpt->latitude / 180.0 * 2147483648.0;
+ lon = wpt->longitude / 180.0 * 2147483648.0;
+ le_write32(&rec->wpt.d103.lat, lat);
+ le_write32(&rec->wpt.d103.lon, lon);
+
+ pdb_write_rec(file_out, 0, ct, ct+1, rec, (char*)vdata - (char*)rec);
+ ct++;
+ xfree(rec);
+}
+
+static void
+data_write(void)
+{
+ if (dbname) {
+ strncpy(file_out->name, dbname, PDB_DBNAMELEN);
+ } else {
+ strncpy(file_out->name, out_fname, PDB_DBNAMELEN);
+ }
+
+ /*
+ * Populate header.
+ */
+ file_out->name[PDB_DBNAMELEN-1] = 0;
+ file_out->attr = PDB_FLAG_BACKUP;
+ file_out->ctime = file_out->mtime = current_time().toTime_t() + 2082844800U;
+
+ file_out->type = MYWPT;
+ file_out->creator = MYCREATOR;
+ file_out->version = 1;
+
+ waypt_disp_all(my_write_wpt);
+}
+
+
+ff_vecs_t gpilots_vecs = {
+ ff_type_file,
+ { (ff_cap)(ff_cap_read | ff_cap_write), (ff_cap)(ff_cap_read | ff_cap_write), ff_cap_none},
+ rd_init,
+ wr_init,
+ rd_deinit,
+ wr_deinit,
+ data_read,
+ data_write,
+ NULL,
+ my_args,
+ CET_CHARSET_ASCII, 0 /* CET-REVIEW */
+};
+#endif
--- /dev/null
+/*
+ Read and write GPSPilot Tracker files.
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+#if PDBFMTS_ENABLED
+#include "pdbfile.h"
+
+#define MYNAME "GPSPilot"
+#define MYTYPE_POINTS 0x706f696e /* poin */
+#define MYTYPE_AIRPORT 0x706f3030 /* po00 */
+#define MYTYPE_CITIES 0x706f3031 /* po01 */
+#define MYTYPE_LNDMRKS 0x706f3032 /* po02 */
+#define MYTYPE_NAVAIDS 0x706f3033 /* po03 */
+#define MYCREATOR 0x47704c69 /* GpLi */
+
+struct record {
+ pdb_32 longitude; /* Big endian, long * 3.6e6 */
+ pdb_32 latitude; /* similarly */
+ pdb_16 elevation; /* meters */
+ pdb_16 magvar; /* magnetic variation in degrees, neg = west */
+};
+
+struct runways {
+ pdb_32 be_longitude; /* Big endian, long * 3.6e6 */
+ pdb_32 be_latitude; /* similarly */
+ pdb_32 en_longitude; /* Big endian, long * 3.6e6 */
+ pdb_32 en_latitude; /* similarly */
+};
+
+static pdbfile* file_in, *file_out;
+static const char* out_fname;
+static char* dbname = NULL;
+static int ct;
+
+static
+arglist_t gpspilot_args[] = {
+ {"dbname", &dbname, "Database name", NULL, ARGTYPE_STRING, ARG_NOMINMAX},
+ ARG_TERMINATOR
+};
+
+static void
+rd_init(const char* fname)
+{
+ file_in = pdb_open(fname, MYNAME);
+}
+
+static void
+rd_deinit(void)
+{
+ pdb_close(file_in);
+ if (dbname) {
+ xfree(dbname);
+ dbname = NULL;
+ }
+}
+
+static void
+wr_init(const char* fname)
+{
+ file_out = pdb_create(fname, MYNAME);
+ out_fname = fname;
+ ct = 0;
+}
+
+static void
+wr_deinit(void)
+{
+ pdb_close(file_out);
+ if (dbname) {
+ xfree(dbname);
+ dbname = NULL;
+ }
+}
+
+static void
+data_read(void)
+{
+ struct record* rec;
+ pdbrec_t* pdb_rec;
+
+ if ((file_in->creator != MYCREATOR)) {
+ fatal(MYNAME ": Not a gpspilot file.\n");
+ }
+
+ switch (file_in->type) {
+ case MYTYPE_AIRPORT:
+ case MYTYPE_POINTS:
+ case MYTYPE_CITIES:
+ case MYTYPE_LNDMRKS:
+ case MYTYPE_NAVAIDS:
+ break;
+ default:
+ fatal(MYNAME ": Not a gpspilot file.\n");
+ }
+
+ for (pdb_rec = file_in->rec_list; pdb_rec; pdb_rec = pdb_rec->next) {
+ waypoint* wpt_tmp;
+ char* vdata;
+
+ wpt_tmp = waypt_new();
+
+ rec = (struct record*) pdb_rec->data;
+ wpt_tmp->longitude = be_read32(&rec->longitude) / 3.6e6;
+ wpt_tmp->latitude = be_read32(&rec->latitude) / 3.6e6;
+ wpt_tmp->altitude =
+ be_read16(&rec->elevation);
+
+ vdata = (char*) pdb_rec->data + sizeof(*rec);
+
+ /*
+ * skip runway records if an airport.
+ */
+ if (pdb_rec->category == 0) {
+ int numRunways;
+ numRunways = be_read16(vdata);
+ vdata += 2;
+ vdata += (sizeof(struct runways) * numRunways);
+ }
+
+ /*
+ * This maping is a bit contrived.
+ * Name is up to 36. ID is up to 9.
+ * Since 'ID' maps more clearly to "shortname" (and this
+ * more likely to be resemble a wayoint name in another
+ * receiver) we use that for shortname and use 'name' as
+ * our description.
+ */
+ wpt_tmp->description = xstrdup(vdata);
+ vdata = vdata + strlen(vdata) + 1;
+
+ wpt_tmp->shortname = xstrdup(vdata);
+ vdata = vdata + strlen(vdata) + 1;
+
+ wpt_tmp->notes = xstrdup(vdata);
+
+ waypt_add(wpt_tmp);
+
+ }
+}
+
+
+static void
+gpspilot_writewpt(const waypoint* wpt)
+{
+ struct record* rec;
+ char* vdata;
+
+ rec = (struct record*) xcalloc(sizeof(*rec)+206,1);
+
+ be_write32(&rec->longitude, si_round(wpt->longitude * 3.6e6));
+ be_write32(&rec->latitude, si_round(wpt->latitude * 3.6e6));
+ be_write16(&rec->elevation, si_round(wpt->altitude));
+ be_write16(&rec->magvar, 0);
+
+ vdata = (char*)rec + sizeof(*rec);
+ if (wpt->description) {
+ strncpy(vdata, wpt->description, 36);
+ vdata[35] = '\0';
+ } else {
+ vdata[0] ='\0';
+ }
+ vdata += strlen(vdata) + 1;
+ if (wpt->shortname) {
+ strncpy(vdata, wpt->shortname, 9);
+ vdata[8] = '\0';
+ } else {
+ vdata[0] ='\0';
+ }
+ vdata += strlen(vdata) + 1;
+
+ if (wpt->notes) {
+ strncpy(vdata, wpt->notes, 161);
+ vdata[160] = '\0';
+ } else {
+ vdata[0] ='\0';
+ }
+ vdata += strlen(vdata) + 1;
+
+ pdb_write_rec(file_out, 0, 2, ct++, (void*)rec, (char*)vdata - (char*)rec);
+
+ xfree(rec);
+}
+
+static void
+data_write(void)
+{
+ if (dbname) {
+ strncpy(file_out->name, dbname, PDB_DBNAMELEN);
+ } else {
+ strncpy(file_out->name, out_fname, PDB_DBNAMELEN);
+ }
+ file_out->name[PDB_DBNAMELEN-1] = 0;
+ file_out->attr = PDB_FLAG_BACKUP;
+ file_out->ctime = file_out->mtime = current_time().toTime_t() + 2082844800U;
+ file_out->type = MYTYPE_POINTS;
+ file_out->creator = MYCREATOR;
+ file_out->version = 0;
+
+ waypt_disp_all(gpspilot_writewpt);
+}
+
+
+ff_vecs_t gpspilot_vecs = {
+ ff_type_file,
+ FF_CAP_RW_WPT,
+ rd_init,
+ wr_init,
+ rd_deinit,
+ wr_deinit,
+ data_read,
+ data_write,
+ NULL,
+ gpspilot_args,
+ CET_CHARSET_ASCII, 0 /* CET-REVIEW */
+};
+#endif
--- /dev/null
+/*
+
+ Support of Palm/OS files from Map&Guide based products like
+ "PowerRoute" 5+6, "Motorrad Routenplaner"
+
+ Copyright (C) 2005 Olaf Klein, o.b.klein@gpsbabel.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+*/
+
+#include <ctype.h>
+#include <math.h>
+
+#include "defs.h"
+#if PDBFMTS_ENABLED
+#include "pdbfile.h"
+#include "jeeps/gpsmath.h"
+
+#define MYNAME "mag_pdb"
+
+#define PROUTE_MAGIC 0x766d6170 /* vmap */
+#define PROUTE_ROUTE 0x49444154 /* IDAT */
+
+static pdbfile* file_in;
+
+static arglist_t magpdb_args[] = {
+ ARG_TERMINATOR
+};
+
+static double
+magpdb_to_degree(const int degx)
+{
+ int m, d, x;
+ double s, res;
+
+ d = degx / 100000;
+ x = degx % 100000;
+ m = x / 1000;
+ x = x % 1000;
+ s = (double)(x) / 10;
+
+ GPS_Math_DegMinSec_To_Deg(d, m, s, &res);
+
+ return res;
+}
+
+static void
+magpdb_read_data(const char* data, const size_t data_len)
+{
+ route_head* route;
+ char* cin = (char*)data;
+ char* cend = cin + data_len;
+
+ route = route_head_alloc();
+ route_add_head(route);
+
+ while (cin < cend) {
+ char* lend;
+ int len;
+
+ lend = strchr(cin, '\x0A');
+ if (lend == NULL) {
+ break;
+ }
+
+ len = (lend - cin);
+ if (len > 0) {
+ double distance;
+ int hour, min;
+ *lend = '\0';
+
+ if (case_ignore_strncmp(cin, "Wegname=", 8) == 0) { /* This only works with the german release */
+ /* test-data created with other releases are welcome */
+ cin += 8;
+ if (*cin != '\0') {
+ route->rte_name = xstrdup(cin);
+ }
+ } else if (case_ignore_strncmp(cin, "Fahrzeit=", 9) == 0) {
+ } else if (case_ignore_strncmp(cin, "Kosten=", 7) == 0) {
+ } else if (case_ignore_strncmp(cin, "Entfernung=", 11) == 0) {
+ }
+ /* check, if line starts with time and distance */
+ else if (3 == sscanf(cin, "%d:%d %lf", &hour, &min, &distance)) {
+ char* buff, *comma;
+
+ /* detect time-format settings, 12,0 or 12.0 */
+
+ comma = strchr(cin, '.');
+ buff = strchr(cin, ',');
+ if (comma == NULL) {
+ comma = buff;
+ } else if ((buff != NULL) && (buff < comma)) {
+ comma = buff;
+ }
+ if (comma != NULL) {
+ char separator = *comma;
+
+ /* now we are looking for a sequence like 0,1 NE (123456,654321) */
+
+ buff = (char*) xmalloc(strlen(cin) + 1); /* safe target space for sscanf( ... */
+
+ comma = cin;
+ while ((comma = strchr(comma, separator))) {
+ int i, xlat, xlon;
+ waypoint* wpt;
+ char* cx;
+
+ comma++;
+
+ if (isdigit(*comma) == 0) {
+ continue;
+ }
+ if (isdigit(*(comma - 2)) == 0) {
+ continue;
+ }
+
+ if (4 != sscanf(comma, "%d %s (%d,%d)", &i, buff, &xlon, &xlat)) {
+ continue;
+ }
+ if (strchr("NESW", *buff) == NULL) {
+ continue; /* north, east, ... */
+ }
+
+ cx = comma - 2; /* go left over delta distance */
+ while (isdigit(*cx) != 0) {
+ *cx-- = '\0';
+ }
+ cin = lrtrim(cin);
+
+ for (i = 0; i < 2; i++) { /* skip time and distance at start of line */
+ cin = strchr(cin, ' ');
+ cin = lrtrim(cin);
+ }
+
+ wpt = waypt_new();
+
+ wpt->latitude = magpdb_to_degree(xlat);
+ wpt->longitude = magpdb_to_degree(xlon);
+ wpt->description = xstrdup(cin);
+
+ cx = strchr(comma, ')'); /* find tailing notes after the coordinates */
+ if (cx != NULL) {
+ char* tail = lrtrim(++cx);
+ if (*tail != '\0') {
+ wpt->notes = xstrdup(tail);
+ }
+ }
+ /* generate some waypoints from our route-only format */
+ if ((*cin != '-') && (case_ignore_strncmp(cin, "bei ", 4) != 0)) {
+ waypt_add(waypt_dupe(wpt));
+ }
+
+ route_add_wpt(route, wpt);
+ break;
+ }
+ xfree(buff);
+ }
+ }
+
+ }
+ cin = lend + 1;
+ }
+}
+
+/* ============================================================================================
+ * &&& gobal callbacks &&&
+ * ----------------------------------------------------------------------------------------- */
+
+static void magpdb_rd_init(const char* fname)
+{
+ file_in = pdb_open(fname, MYNAME);
+}
+
+static void magpdb_rd_deinit(void)
+{
+ pdb_close(file_in);
+}
+
+static void magpdb_read(void)
+{
+ pdbrec_t* pdb_rec;
+
+ is_fatal((file_in->creator != PROUTE_MAGIC), /* identify the database */
+ MYNAME ": Not a Map&Guide pdb file (0x%08x).", file_in->creator);
+
+ is_fatal((file_in->version != 0), /* only version "0" currently seen and tested */
+ MYNAME ": This file is from an unsupported version (%d) of Map&Guide and is unsupported.", file_in->version + 5);
+
+ is_fatal((file_in->type != PROUTE_ROUTE),
+ MYNAME ": Unknown pdb data type (0x%08x).", file_in->type);
+
+ for (pdb_rec = file_in->rec_list; pdb_rec; pdb_rec = pdb_rec->next) {
+ char* data = (char*)pdb_rec->data;
+
+ if (be_read16(data) == 0) {
+ int len = be_read16(data + 2);
+ magpdb_read_data(data + 4, len);
+ }
+ }
+}
+
+/* ======================================================================================= */
+
+ff_vecs_t magpdb_vecs = {
+ ff_type_file,
+ { ff_cap_read, ff_cap_none, ff_cap_read }, /* real route + emulated waypoints */
+ magpdb_rd_init,
+ NULL,
+ magpdb_rd_deinit,
+ NULL,
+ magpdb_read,
+ NULL,
+ NULL,
+ magpdb_args,
+ CET_CHARSET_MS_ANSI, 1 /* CET-REVIEW */
+};
+#endif
--- /dev/null
+/*
+ Read and write Magellan Navigator Companion files.
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+#if PDBFMTS_ENABLED
+#include "pdbfile.h"
+
+#define MYNAME "Companion Waypoints"
+#define MYTYPE 0x54777074 /* Twpt */
+#define MYCREATOR 0x4d47747a /* MGtz */
+
+struct record {
+ pdb_16 crt_sec; /* Big endian, creation time */
+ pdb_16 crt_min;
+ pdb_16 crt_hour;
+ pdb_16 crt_mday;
+ pdb_16 crt_mon; /* 1 = Jan */
+ pdb_16 crt_year; /* includes century. */
+ pdb_16 unknown;
+ pdb_16 xx_sec; /* appears to be time, but we don't know what it is. */
+ pdb_16 xx_min;
+ pdb_16 xx_hour;
+ pdb_16 xx_mday;
+ pdb_16 xx_mon;
+ pdb_16 xx_year;
+ pdb_16 unknown2;
+ pdb_32 latitude; /* lat * 1e5 */
+ pdb_32 longitude; /* lon * 1e5 */
+ pdb_32 elevation; /* meters */
+ char plot; /* 1 = plot on map screen. default = 0 */
+ char unknown3; /* always 'a' */
+};
+
+static pdbfile* file_in;
+static pdbfile* file_out;
+static short_handle mkshort_handle;
+static int ct;
+
+static void
+rd_init(const char* fname)
+{
+ file_in = pdb_open(fname, MYNAME);
+}
+
+static void
+rd_deinit(void)
+{
+ pdb_close(file_in);
+}
+
+static void
+wr_init(const char* fname)
+{
+ file_out = pdb_create(fname, MYNAME);
+ mkshort_handle = mkshort_new_handle();
+ setshort_length(mkshort_handle, 20);
+ ct = 0;
+}
+
+static void
+wr_deinit(void)
+{
+ pdb_close(file_out);
+ mkshort_del_handle(&mkshort_handle);
+}
+
+static void
+data_read(void)
+{
+ struct record* rec;
+ pdbrec_t* pdb_rec;
+
+ if ((file_in->creator != MYCREATOR) || (file_in->type != MYTYPE)) {
+ fatal(MYNAME ": Not a Magellan Navigator file.\n");
+ }
+
+ for (pdb_rec = file_in->rec_list; pdb_rec; pdb_rec = pdb_rec->next) {
+ waypoint* wpt_tmp;
+ char* vdata;
+ struct tm tm;
+
+ memset(&tm, 0, sizeof(tm));
+ wpt_tmp = waypt_new();
+ rec = (struct record*) pdb_rec->data;
+ wpt_tmp->altitude = be_read32(&rec->elevation);
+
+ wpt_tmp->longitude = be_read32(&rec->longitude) / 1e5;
+ wpt_tmp->latitude = be_read32(&rec->latitude) / 1e5;
+
+ vdata = (char*) pdb_rec->data + sizeof(*rec);
+
+ wpt_tmp->shortname = xstrdup(vdata);
+ vdata += strlen(vdata) + 1;
+
+ wpt_tmp->description = xstrdup(vdata);
+ vdata += strlen(vdata) + 1;
+
+ tm.tm_sec = be_read16(&rec->crt_sec);
+ tm.tm_min = be_read16(&rec->crt_min);
+ tm.tm_hour = be_read16(&rec->crt_hour);
+ tm.tm_mday = be_read16(&rec->crt_mday);
+ tm.tm_mon = be_read16(&rec->crt_mon) - 1;
+ tm.tm_year = be_read16(&rec->crt_year) - 1900;
+ if (mkgmtime(&tm) > 0) {
+ wpt_tmp->SetCreationTime(mktime(&tm));
+ }
+ waypt_add(wpt_tmp);
+
+ }
+}
+
+
+static void
+my_writewpt(const waypoint* wpt)
+{
+ struct record* rec;
+ char* vdata;
+ const char* sn = global_opts.synthesize_shortnames ?
+ mkshort_from_wpt(mkshort_handle, wpt) :
+ wpt->shortname;
+
+ rec = (struct record*) xcalloc(sizeof(*rec)+56,1);
+
+ time_t tm_t;
+ struct tm* tm;
+ tm = NULL;
+ if (wpt->creation_time.isValid()) {
+ const time_t tt = wpt->creation_time.toTime_t();
+ tm = gmtime(&tt);
+ }
+ if (!tm) {
+ tm_t = current_time().toTime_t();
+ tm = gmtime(&tm_t);
+ }
+
+ be_write16(&rec->crt_sec, tm->tm_sec);
+ be_write16(&rec->crt_min, tm->tm_min);
+ be_write16(&rec->crt_hour, tm->tm_hour);
+ be_write16(&rec->crt_mday, tm->tm_mday);
+ be_write16(&rec->crt_mon, tm->tm_mon + 1);
+ be_write16(&rec->crt_year, tm->tm_year + 1900);
+
+ be_write16(&rec->unknown, 0);
+
+ be_write16(&rec->xx_sec, tm->tm_sec);
+ be_write16(&rec->xx_min, tm->tm_min);
+ be_write16(&rec->xx_hour, tm->tm_hour);
+ be_write16(&rec->xx_mday, tm->tm_mday);
+ be_write16(&rec->xx_mon, tm->tm_mon + 1);
+ be_write16(&rec->xx_year, tm->tm_year + 1900);
+
+ be_write16(&rec->unknown2, 0);
+
+ be_write32(&rec->longitude, si_round(wpt->longitude * 100000.0));
+ be_write32(&rec->latitude, si_round(wpt->latitude * 100000.0));
+ be_write32(&rec->elevation, (unsigned int)(wpt->altitude));
+
+ rec->plot = 0;
+ rec->unknown3 = 'a';
+
+ vdata = (char*)rec + sizeof(*rec);
+ if (sn) {
+ strncpy(vdata, sn, 21);
+ vdata[20] = '\0';
+ } else {
+ vdata[0] ='\0';
+ }
+ vdata += strlen(vdata) + 1;
+ if (wpt->description) {
+ strncpy(vdata, wpt->description, 33);
+ vdata[32] = '\0';
+ } else {
+ vdata[0] = '\0';
+ }
+ vdata += strlen(vdata) + 1;
+ vdata[0] = '\0';
+ vdata[1] = '\0';
+ vdata += 2;
+
+ pdb_write_rec(file_out, 0, 0, ct++, rec, (char*)vdata - (char*)rec);
+
+ xfree(rec);
+}
+
+static void
+data_write(void)
+{
+ static const char* appinfo =
+ "\0\x01"
+ "User\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\x01\x02\x03\x04\x05\x06\x07\x08"
+ "\x09\x0a\x0b\x0c\x0d\x0e\x0f\0\0";
+
+ strncpy(file_out->name, "Companion Waypoints", PDB_DBNAMELEN);
+ file_out->attr = PDB_FLAG_BACKUP;
+ file_out->ctime = file_out->mtime = current_time().toTime_t() + 2082844800U;
+ file_out->type = MYTYPE; /* CWpt */
+ file_out->creator = MYCREATOR; /* cGPS */
+ file_out->version = 1;
+ file_out->appinfo = (void*)appinfo;
+ file_out->appinfo_len = 276;
+
+ waypt_disp_all(my_writewpt);
+}
+
+
+ff_vecs_t magnav_vec = {
+ ff_type_file,
+ FF_CAP_RW_WPT,
+ rd_init,
+ wr_init,
+ rd_deinit,
+ wr_deinit,
+ data_read,
+ data_write,
+ NULL,
+ NULL,
+ CET_CHARSET_ASCII, 0 /* CET-REVIEW */
+};
+#endif
--- /dev/null
+/*
+ Read and write Mapopolis files.
+
+ Copyright (C) 2003 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+#if PDBFMTS_ENABLED
+#include "pdbfile.h"
+
+#define MYNAME "Companion Waypoints"
+#define MYTYPE 0x64617461 /* Platdata */
+#define MYCREATOR 0x5061746c /* Plat */
+
+#define LONDIV (85116.044444)
+#define LATDIV (1000000.0/9)
+#define LONDIV2 (85116.044444/2)
+#define LATDIV2 (1000000.0/(9*2))
+
+
+struct record0 {
+ char unk[6];
+ pdb_32 lon1;
+ pdb_32 lat1;
+ pdb_32 lon2;
+ pdb_32 lat2;
+ pdb_32 lonD;
+ pdb_32 latD;
+ char name[31+1];
+ char unk2[35];
+ char demo;
+ char unk3[4];
+ unsigned char expcode[4];
+ /* ... more stuff ... */
+};
+
+double Lat1, Lon1;
+double Lat2, Lon2;
+double LatD, LonD;
+
+struct record {
+ char unknown[10];
+ pdb_16 unk1;
+ pdb_16 unk2;
+ pdb_16 lon1d;
+ pdb_16 lat1d;
+ pdb_16 lon2d;
+ pdb_16 lat2d;
+};
+
+static pdbfile* file_in, *file_out;
+static short_handle mkshort_handle;
+
+static void
+rd_init(const char* fname)
+{
+ file_in = pdb_open(fname, MYNAME);
+}
+
+static void
+rd_deinit(void)
+{
+ pdb_close(file_in);
+}
+
+static void
+wr_init(const char* fname)
+{
+ file_out = pdb_create(fname, MYNAME);
+ mkshort_handle = mkshort_new_handle();
+ setshort_length(mkshort_handle, 20);
+}
+
+static void
+wr_deinit(void)
+{
+ pdb_close(file_out);
+ mkshort_del_handle(&mkshort_handle);
+}
+
+void convert_rec0(struct record0* rec0)
+{
+ Lon1 = be_read32(&rec0->lon1) / LONDIV;
+ Lat1 = be_read32(&rec0->lat1) / LATDIV;
+ Lon2 = be_read32(&rec0->lon2) / LONDIV;
+ Lat2 = be_read32(&rec0->lat2) / LATDIV;
+ LonD = be_read32(&rec0->lonD) / LONDIV2;
+ LatD = be_read32(&rec0->latD) / LATDIV2;
+
+// printf("%s: %.5f %.5f %.5f %.5f %.5f %.5f\n",
+// rec0->name, Lat1, Lon1, Lat2, Lon2, LatD, LonD);
+
+
+}
+
+/*
+ * * Decode the information field
+ * */
+void
+decode(char* buf)
+{
+ int i;
+
+ for (i = 0; buf[i]; ++i) {
+ buf[i] = buf[i] ^ ((i % 96) & 0xf);
+ }
+}
+
+static void
+data_read(void)
+{
+ struct record* rec;
+ pdbrec_t* pdb_rec;
+
+ if ((file_in->creator != MYCREATOR) || (file_in->type != MYTYPE)) {
+ fatal(MYNAME ": Not a Magellan Navigator file.\n");
+ }
+
+ pdb_rec = file_in->rec_list;
+ convert_rec0((struct record0*) pdb_rec->data);
+
+// for(pdb_rec = pdb->rec_index.rec; pdb_rec; pdb_rec=pdb_rec->next) {
+ for (pdb_rec = pdb_rec->next; pdb_rec; pdb_rec=pdb_rec->next) {
+ waypoint* wpt_tmp;
+ char* vdata = 0;
+ char* edata;
+ struct tm tm = {0};
+
+ rec = (struct record*) pdb_rec->data;
+ edata = (char*) rec + pdb_rec->size;
+
+ for (; vdata < edata; rec = (struct record*) vdata) {
+ wpt_tmp = waypt_new();
+ wpt_tmp->latitude = Lat1 +
+ be_read16(&rec->lat1d) / LATDIV2;
+ wpt_tmp->longitude = Lon1 +
+ be_read16(&rec->lon1d) / LONDIV2;
+
+ vdata = (char*) rec + sizeof(*rec);
+ wpt_tmp->description = xstrdup(vdata);
+ vdata += strlen(wpt_tmp->description) + 1 + 6;
+
+ while (*vdata == 0x40) {
+ vdata++;
+ }
+ decode(vdata);
+ wpt_tmp->notes = xstrdup(vdata);
+ vdata += strlen(wpt_tmp->notes) + 1;
+
+ waypt_add(wpt_tmp);
+ }
+ }
+}
+
+
+static void
+my_writewpt(const waypoint* wpt)
+{
+#if 0
+ struct record* rec;
+ static int ct;
+ struct tm* tm;
+ char* vdata;
+ time_t tm_t;
+ const char* sn = global_opts.synthesize_shortnames ?
+ mkshort(mkshort_handle, wpt->description) :
+ wpt->shortname;
+
+ rec = xcalloc(sizeof(*rec)+56,1);
+
+ tm = NULL;
+ if (wpt->creation_time) {
+ tm = gmtime(&wpt->creation_time);
+ }
+ if (!tm) {
+ tm_t = current_time();
+ tm = gmtime(&tm_t);
+ }
+
+ be_write16(&rec->crt_sec, tm->tm_sec);
+ be_write16(&rec->crt_min, tm->tm_min);
+ be_write16(&rec->crt_hour, tm->tm_hour);
+ be_write16(&rec->crt_mday, tm->tm_mday);
+ be_write16(&rec->crt_mon, tm->tm_mon + 1);
+ be_write16(&rec->crt_year, tm->tm_mon + 1900);
+
+ be_write16(&rec->unknown, 0);
+
+ be_write16(&rec->xx_sec, tm->tm_sec);
+ be_write16(&rec->xx_min, tm->tm_min);
+ be_write16(&rec->xx_hour, tm->tm_hour);
+ be_write16(&rec->xx_mday, tm->tm_mday);
+ be_write16(&rec->xx_mon, tm->tm_mon + 1);
+ be_write16(&rec->xx_year, tm->tm_mon + 1900);
+
+ be_write16(&rec->unknown2, 0);
+
+ be_write32(&rec->longitude, si_round(wpt->longitude * 100000.0));
+ be_write32(&rec->latitude, si_round(wpt->latitude * 100000.0));
+ be_write32(&rec->elevation, wpt->altitude);
+
+ rec->plot = 0;
+ rec->unknown3 = 'a';
+
+ vdata = (char*)rec + sizeof(*rec);
+ if (sn) {
+ strncpy(vdata, sn, 21);
+ vdata[20] = '\0';
+ } else {
+ vdata[0] ='\0';
+ }
+ vdata += strlen(vdata) + 1;
+ if (wpt->description) {
+ strncpy(vdata, wpt->description, 33);
+ vdata[32] = '\0';
+ } else {
+ vdata[0] = '\0';
+ }
+ vdata += strlen(vdata) + 1;
+ vdata[0] = '\0';
+ vdata[1] = '\0';
+ vdata += 2;
+
+ pdb_write(file_out, 0, rec, (char*)vdata - (char*)rec);
+
+ xfree(rec);
+#endif
+}
+
+static void
+data_write(void)
+{
+ static char* appinfo =
+ "\0\x01"
+ "User\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\x01\x02\x03\x04\x05\x06\x07\x08"
+ "\x09\x0a\x0b\x0c\x0d\x0e\x0f\0\0";
+
+ strncpy(file_out->name, "Companion Waypoints", PDB_DBNAMELEN);
+ file_out->name[PDB_DBNAMELEN-1] = 0;
+ file_out->attr = PDB_FLAG_BACKUP;
+ file_out->ctime = file_out->mtime = current_time() + 2082844800U;
+ file_out->type = MYTYPE; /* CWpt */
+ file_out->creator = MYCREATOR; /* cGPS */
+ file_out->version = 1;
+ file_out->appinfo = (void*)appinfo;
+ file_out->appinfo_len = 276;
+
+ waypt_disp_all(my_writewpt);
+}
+
+
+ff_vecs_t mapopolis_vecs = {
+ ff_type_file,
+ FF_CAP_RW_WPT,
+ rd_init,
+ wr_init,
+ rd_deinit,
+ wr_deinit,
+ data_read,
+ data_write,
+ NULL,
+ NULL,
+ CET_CHARSET_ASCII, 0 /* CET-REVIEW */
+};
+#endif
--- /dev/null
+/*
+
+ Support for Microsoft AutoRoute 2002 ".axe" files,
+
+ Copyright (C) 2005,2007,2008 Olaf Klein, o.b.klein@gpsbabel.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+*/
+
+#include "defs.h"
+#include "jeeps/gpsmath.h"
+#include <ctype.h>
+
+#define MYNAME "msroute"
+
+#undef OLE_DEBUG
+
+static gbfile* fin;
+
+static arglist_t msroute_args[] = {
+ ARG_TERMINATOR
+};
+
+/* MS-AutoRoute structures */
+
+typedef struct msroute_head_s {
+ uint32_t U1; /* 58/02/00/00 */
+ char masm[4]; /* "MASM " */
+ uint32_t U2;
+ uint32_t U3;
+ int32_t waypts;
+ uint32_t U5;
+ uint32_t U6;
+ uint32_t U7;
+ uint32_t U8;
+ uint32_t U9;
+ uint32_t U10;
+ uint32_t U11;
+ uint32_t U12;
+ uint32_t U13;
+ uint32_t U14;
+ uint32_t U15;
+ uint32_t U16;
+// short U17;
+// char U18;
+} msroute_head_t;
+
+#define MSROUTE_OBJ_NAME "Journey"
+
+/* simple ole file reader */
+
+#define OLE_MAX_NAME_LENGTH 32
+#define OLE_HEAD_FAT1_CT (512-0x4c)/4
+
+#define BLOCKS(a, b) (((a) + (b) - 1) / (b))
+
+static const unsigned char ole_magic[8] = {
+ 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1
+};
+
+/*
+ The ole implementation looks like a FAT filesystem.
+ Thatswhy i use in code fat1 as item for the "big blocks" or bbd
+ and fat2 for "small blocks" (sbd).
+
+ Remarks:
+
+ * in the moment ole_size1 and sector_sz represents the same value
+ * in OLE_DEBUG mode: successfully tested with 64MB++ standard MS doc's (PowerPoint, Word)
+*/
+
+typedef struct ole_head_s {
+ char magic[8];
+ char clsid[16];
+ uint16_t rev; /* offset 0x18 */
+ uint16_t ver; /* offset 0x1a */
+ int16_t byte_order; /* offset 0x1c */
+ uint16_t fat1_size_shift; /* offset 0x1e */
+ uint16_t fat2_size_shift; /* offset 0x20 */
+ uint16_t U7; /* offset 0x22 */
+ uint32_t U8; /* offset 0x24 */
+ uint32_t U9; /* offset 0x28 */
+ int32_t fat1_blocks; /* offset 0x2c */
+ int32_t prop_start; /* offset 0x30 */
+ uint32_t U12; /* offset 0x34 */
+ uint32_t fat1_min_size; /* offset 0x38 */
+ int32_t fat2_start; /* offset 0x3c */
+ int32_t fat2_blocks; /* offset 0x40 */
+ int32_t fat1_extra_start; /* offset 0x44 */
+ int32_t fat1_extra_ct; /* offset 0x48 */
+ int32_t fat1[OLE_HEAD_FAT1_CT]; /* offset 0x4c */
+} ole_head_t;
+
+typedef struct ole_prop_s {
+ uint16_t name[32];
+ uint16_t name_sz; /* offset 0x40 */
+ char ole_typ; /* offset 0x42 */
+ char U1; /* offset 0x43 */
+ uint32_t previous; /* offset 0x44 */
+ uint32_t next; /* offset 0x48 */
+ uint32_t dir; /* offset 0x4c */
+ uint32_t U5; /* offset 0x50 */
+ uint32_t U6; /* offset 0x54 */
+ uint32_t U7; /* offset 0x58 */
+ uint32_t U8; /* offset 0x5c */
+ uint32_t U9; /* offset 0x60 */
+ uint32_t U10; /* offset 0x64 */
+ uint32_t U11; /* offset 0x68 */
+ uint32_t U12; /* offset 0x6c */
+ uint32_t U13; /* offset 0x70 */
+ int32_t first_sector; /* offset 0x74 */
+ int32_t data_sz; /* offset 0x78 */
+ uint32_t U16; /* offset 0x7c */
+} ole_prop_t;
+
+#define DIR_ITEM_SIZE sizeof(ole_prop_t)
+
+static int sector_sz = 512;
+
+#ifndef min
+#define min(a,b) ((a) < (b)) ? (a) : (b)
+#endif
+#ifndef max
+#define max(a,b) ((a) > (b)) ? (a) : (b)
+#endif
+
+static int32_t* ole_fat1 = NULL;
+static int32_t* ole_fat2 = NULL;
+static int ole_fat1_ct;
+static int ole_fat2_ct;
+static int ole_size1;
+static int ole_size2;
+static int ole_size1_min = 4096;
+static ole_prop_t* ole_dir = NULL;
+static int ole_dir_ct;
+static ole_prop_t* ole_root = NULL;
+static char** ole_root_sec = NULL;
+static int ole_root_sec_ct;
+
+/* local helpers */
+
+static void
+le_read32_buff(int* buff, const int count)
+{
+ int i;
+ for (i = 0; i < count; i++) {
+ buff[i] = le_read32(&buff[i]);
+ }
+}
+
+/* simple OLE file reader */
+
+static void
+ole_read_sector(const int sector, void* target, const char full)
+{
+ int res;
+
+ res = gbfseek(fin, (sector + 1) * sector_sz, SEEK_SET);
+ is_fatal((res != 0), MYNAME ": Could not seek file to sector %d!", sector + 1);
+ res = gbfread(target, 1, sector_sz, fin);
+ is_fatal(
+ ((res < 0) || (full && (res < sector_sz))),
+ MYNAME ": Read error (%d, sector %d) on file \"%s\"!", res, sector, fin->name);
+}
+
+static ole_prop_t*
+ole_find_property(const char* property)
+{
+ int i;
+
+ for (i = 0; i < ole_dir_ct; i++) {
+ int len, test;
+ char* str;
+ ole_prop_t* item;
+
+ item = &ole_dir[i];
+ if ((item->ole_typ != 1) && (item->ole_typ != 2) && (item->ole_typ != 5)) {
+ continue;
+ }
+ if ((item->data_sz <= 0) || (item->name_sz <= 0)) {
+ continue;
+ }
+
+ len = min(OLE_MAX_NAME_LENGTH, item->name_sz / 2);
+ str = cet_str_uni_to_utf8((short*)&item->name, len);
+ test = case_ignore_strcmp(str, property);
+ xfree(str);
+
+ if (test == 0) {
+ return item;
+ }
+ }
+ is_fatal((1), MYNAME ": \"%s\" not in property catalog!", property);
+ return 0;
+}
+
+static char*
+ole_read_stream(const ole_prop_t* property)
+{
+ const char* action = "ole_read_stream";
+ int len, sector, big, blocksize, offs, left;
+ int i;
+ int* fat;
+ char* buff;
+
+ len = property->data_sz;
+
+ if (len >= ole_size1_min) {
+ big = 1;
+ blocksize = ole_size1;
+ fat = ole_fat1;
+ } else {
+ big = 0;
+ blocksize = ole_size2;
+ fat = ole_fat2;
+ }
+
+ offs = 0;
+ left = len;
+ sector = property->first_sector;
+
+ i = ((len + blocksize - 1) / blocksize) * blocksize;
+ buff = (char*) xmalloc(i); /* blocksize aligned */
+
+ if (big != 0) {
+ while (left > 0) {
+ int bytes = (left <= blocksize) ? left : blocksize;
+ ole_read_sector(sector, buff + offs, (bytes >= sector_sz));
+ left -= bytes;
+ offs += bytes;
+ if (left > 0) {
+ sector = fat[sector];
+ is_fatal((sector < 0), MYNAME ": Broken stream (%s)!", action);
+ }
+ }
+ } else {
+ int chain = sector;
+ int blocks = (len + blocksize - 1) / blocksize;
+ int blocks_per_sector = sector_sz / blocksize;
+
+ offs = 0;
+
+ while (blocks-- > 0) {
+ char* temp;
+ int block_offs;
+
+ is_fatal((chain < 0), MYNAME ": Broken stream (%s)!", action);
+
+ sector = chain / blocks_per_sector;
+ is_fatal((sector >= ole_root_sec_ct), MYNAME ": Broken stream (%s)!", action);
+
+ temp = ole_root_sec[sector];
+ is_fatal((temp == NULL), MYNAME ": Broken stream (%s)!", action);
+
+ block_offs = (chain % blocks_per_sector) * blocksize;
+
+ memcpy(buff + offs, temp + block_offs, blocksize);
+
+ offs += blocksize;
+ chain = fat[chain];
+ }
+ }
+ return buff;
+}
+
+
+static char*
+ole_read_property_stream(const char* property_name, int* data_sz)
+{
+ ole_prop_t* property;
+ char* result;
+
+ if ((property = ole_find_property(property_name)) == NULL) {
+ return NULL;
+ }
+
+ result = ole_read_stream(property);
+ if ((result != NULL) && (data_sz != NULL)) {
+ *data_sz = property->data_sz;
+ }
+
+ return result;
+}
+
+#ifdef OLE_DEBUG
+
+static void
+ole_test_properties()
+{
+ int i;
+
+ for (i = 0; i < ole_dir_ct; i++) {
+ char* temp;
+ char name[OLE_MAX_NAME_LENGTH + 1];
+ ole_prop_t* p = &ole_dir[i];
+
+ if ((p->ole_typ != 1) && (p->ole_typ != 2) && (p->ole_typ != 5)) {
+ continue;
+ }
+ if ((p->data_sz <= 0) || (p->name_sz <= 0)) {
+ continue;
+ }
+
+ temp = cet_str_uni_to_utf8(&p->name, min(p->name_sz / 2, OLE_MAX_NAME_LENGTH));
+ strncpy(name, temp, sizeof(name));
+ xfree(temp);
+
+ printf(MYNAME ": ole_test_properties for \"%s\" (%d bytes):", name, p->data_sz);
+
+ if ((case_ignore_strcmp(name, "Root Entry") == 0) ||
+ (p->data_sz < ole_size1_min)) {
+ printf(" skipped...\n");
+ continue;
+ } else {
+ int sector = p->first_sector;
+ int data_sz = p->data_sz;
+ int block_size = ole_size1; /* sector_sz */
+
+ printf("\n");
+
+ while ((data_sz > 0) && (sector >= 0)) {
+ int bytes = (data_sz > block_size) ? block_size : data_sz;
+ int prev = sector;
+
+ data_sz -= bytes;
+ sector = ole_fat1[sector];
+ if (sector == -3) {
+ printf(MYNAME ": special block at %d\n", prev);
+ if ((prev + 2) < ole_fat1_ct) {
+ sector = ole_fat1[prev + 1];
+ }
+ printf(MYNAME "-new sector: %d\n", sector);
+ }
+ }
+ is_fatal((data_sz != 0), MYNAME ": Error in fat1 chain, sector = %d, %d bytes (=%d blocks) left!",
+ sector, data_sz, BLOCKS(data_sz, block_size));
+ }
+ }
+}
+#endif
+
+static void
+ole_init(void)
+{
+ ole_head_t head;
+ int i, i_offs, sector, count, left;
+ int fat1_extra[128];
+
+ ole_fat1 = NULL;
+ ole_fat2 = NULL;
+
+ sector_sz = 512; /* fixed for the moment */
+
+ is_fatal((sizeof(head) != sector_sz),
+ MYNAME ": (!) internal error - invalid header size (%lu)!",
+ (unsigned long) sizeof(head));
+
+ memset(&head, 0, sizeof(head));
+ gbfread(&head, sizeof(head), 1, fin);
+
+ is_fatal((strncmp(head.magic, (char*) ole_magic, sizeof(ole_magic)) != 0), MYNAME ": No MS document.");
+
+ head.rev = le_read16(&head.rev);
+ head.ver = le_read16(&head.ver);
+ head.byte_order = le_read16(&head.byte_order);
+ head.fat1_size_shift = le_read16(&head.fat1_size_shift);
+ head.fat2_size_shift = le_read16(&head.fat2_size_shift);
+ head.fat1_blocks = le_read32(&head.fat1_blocks);
+ head.prop_start = le_read32(&head.prop_start);
+ head.fat1_min_size = le_read32(&head.fat1_min_size);
+ head.fat2_start = le_read32(&head.fat2_start);
+ head.fat2_blocks = le_read32(&head.fat2_blocks);
+ head.fat1_extra_start = le_read32(&head.fat1_extra_start);
+ head.fat1_extra_ct = le_read32(&head.fat1_extra_ct);
+ le_read32_buff(&head.fat1[0], OLE_HEAD_FAT1_CT);
+
+ ole_size1 = (1 << head.fat1_size_shift);
+ ole_size2 = (1 << head.fat2_size_shift);
+ ole_size1_min = head.fat1_min_size;
+
+#ifdef OLE_DEBUG
+ printf(MYNAME "-head: (version.revision) = %d.%d\n", head.ver, head.rev);
+ printf(MYNAME "-head: byte-order = %d\n", head.byte_order);
+ printf(MYNAME "-head: big fat start sector = %d (0x%x)\n", head.fat1[0], (head.fat1[0] + 1) * 512);
+ printf(MYNAME "-head: big fat blocks = %d\n", head.fat1_blocks);
+ printf(MYNAME "-head: big fat block size = %d\n", (1 << head.fat1_size_shift));
+ printf(MYNAME "-head: small fat start sector = %d\n", head.fat2_start);
+ printf(MYNAME "-head: small fat blocks = %d\n", head.fat2_blocks);
+ printf(MYNAME "-head: small fat block size = %d\n", (1 << head.fat2_size_shift));
+ printf(MYNAME "-head: big fat minimum length = %d\n", head.fat1_min_size);
+ printf(MYNAME "-head: property catalog start sector = %d\n", head.prop_start);
+ printf(MYNAME "-head: additional big fat blocks = %d\n", head.fat1_extra_ct);
+ printf(MYNAME "-head: additional big fat start sector = %d (0x%x)\n", head.fat1_extra_start, (head.fat1_extra_start + 1) * 512);
+#endif
+
+ is_fatal((head.byte_order != -2), MYNAME ": Unsupported byte-order %d", head.byte_order);
+#if 0
+ sector_sz = ole_size1; /* i'll implement this, if i get an MS-doc (ole) */
+ /* with "sector_sz" other than 512 */
+#else
+ is_fatal((ole_size1 != 512), MYNAME ": Unsupported sector size %d", ole_size1);
+#endif
+ ole_fat1 = (int32_t*) xmalloc(head.fat1_blocks * sector_sz);
+ ole_fat1_ct = (head.fat1_blocks * sector_sz) / sizeof(int32_t);
+
+#ifdef OLE_DEBUG
+ printf(MYNAME "-big fat: %d maximum sectors, size in memory %d, max. datasize %d bytes\n",
+ ole_fat1_ct, head.fat1_blocks * sector_sz, head.fat1_blocks * sector_sz * sector_sz / sizeof(int32_t));
+#endif
+
+ i_offs = 0; /* load "big fat" into memory */
+ left = head.fat1_blocks;
+ count = (left > OLE_HEAD_FAT1_CT) ? OLE_HEAD_FAT1_CT : left;
+
+ for (i = 0; i < count; i++) {
+ sector = head.fat1[i];
+ ole_read_sector(sector, &ole_fat1[i_offs], 1);
+ i_offs += ole_size1 / 4;
+ }
+
+ left -= count;
+
+ if (left > 0) {
+ sector = head.fat1_extra_start;
+
+ while ((left > 0) && (sector >= 0)) {
+ ole_read_sector(sector, &fat1_extra, 1);
+ le_read32_buff(&fat1_extra[0], 128);
+
+ count = (left < 127) ? left : 127;
+ for (i = 0; i < count; i++) {
+ ole_read_sector(fat1_extra[i], &ole_fat1[i_offs], 1);
+ i_offs += ole_size1 / 4;
+ }
+ left -= count;
+ if (left > 0) {
+ sector = fat1_extra[127];
+ }
+ }
+ is_fatal((left > 0), MYNAME ": Broken stream!");
+ }
+ if (ole_fat1_ct > 0) {
+ le_read32_buff(&ole_fat1[0], ole_fat1_ct);
+ }
+
+
+ /* load fat2 "small fat" into memory */
+
+ sector = head.fat2_start;
+ if (sector >= 0) {
+ count = 0;
+ do {
+ if (ole_fat2 == NULL) {
+ ole_fat2 = (int*)xmalloc((count + 1) * sector_sz);
+ } else {
+ ole_fat2 = (int*)xrealloc(ole_fat2, (count + 1) * sector_sz);
+ }
+
+ ole_read_sector(sector, (char*)ole_fat2 + (count * sector_sz), 1);
+ sector = ole_fat1[sector];
+
+ count++;
+ } while (sector >= 0);
+
+ ole_fat2_ct = (count * sector_sz) / sizeof(int32_t);
+ if (ole_fat2_ct > 0) {
+ le_read32_buff(&ole_fat2[0], ole_fat2_ct);
+ }
+ }
+
+ /* load directory (property catalog) */
+
+ sector = head.prop_start;
+ is_fatal((sector < 0), MYNAME ": Invalid file (no property catalog)!");
+
+ count = 0;
+ while (sector >= 0) {
+ if (ole_dir == NULL) {
+ ole_dir = (ole_prop_t*)xmalloc((count + 1) * sector_sz);
+ } else {
+ ole_dir = (ole_prop_t*)xrealloc(ole_dir, (count + 1) * sector_sz);
+ }
+
+ ole_read_sector(sector, (char*)ole_dir + (count * sector_sz), 1);
+ sector = ole_fat1[sector];
+
+ count++;
+ }
+ ole_dir_ct = (count * sector_sz) / sizeof(ole_prop_t);
+
+ /* fix endianess of property catalog */
+
+ for (i = 0; i < ole_dir_ct; i++) {
+ ole_prop_t* item = &ole_dir[i];
+
+ item->first_sector = le_read32(&item->first_sector);
+ item->data_sz = le_read32(&item->data_sz);
+ }
+
+ ole_root = ole_find_property("Root Entry");
+
+ /* read fat2 data sectors given by "Root Entry" */
+
+ ole_root_sec_ct = (ole_root->data_sz + (sector_sz - 1)) / sector_sz;
+ ole_root_sec = (char**) xcalloc(ole_root_sec_ct + 1, sizeof(char*));
+
+ i = 0;
+ sector = ole_root->first_sector;
+ while (sector >= 0) {
+ char* temp;
+
+ temp = ole_root_sec[i++] = (char*) xmalloc(sector_sz);
+
+ ole_read_sector(sector, temp, 1);
+ sector = ole_fat1[sector];
+ }
+#ifdef OLE_DEBUG
+ ole_test_properties();
+#endif
+}
+
+static void
+ole_deinit(void)
+{
+ if (ole_root_sec != NULL) {
+ int i;
+ for (i = 0; i < ole_root_sec_ct; i++) {
+ char* c;
+ if ((c = ole_root_sec[i])) {
+ xfree(c);
+ }
+ }
+ xfree(ole_root_sec);
+ }
+ if (ole_fat1 != NULL) {
+ xfree(ole_fat1);
+ }
+ if (ole_fat2 != NULL) {
+ xfree(ole_fat2);
+ }
+ if (ole_dir != NULL) {
+ xfree(ole_dir);
+ }
+}
+
+/* global MS AutoRoute functions */
+
+static void
+msroute_read_journey(void)
+{
+ int bufsz = 0;
+ char* buff;
+
+ buff = ole_read_property_stream(MSROUTE_OBJ_NAME, &bufsz);
+
+ if ((buff != NULL) && (bufsz > 0)) {
+ msroute_head_t* head = (msroute_head_t*)buff;
+ unsigned char* cin, *cend;
+ int count = 0;
+ route_head* route;
+ waypoint* wpt;
+ char version;
+
+ is_fatal((strncmp(head->masm, "MASM", 4) != 0), MYNAME ": Invalid or unknown data!");
+
+ version = buff[0x14];
+ is_fatal((version < 1) || (version > 7), MYNAME ": Unsupported version %d!", version);
+
+ cin = (unsigned char*)buff + 71; // (at least?) sizeof(msroute_head_t);
+ cend = (unsigned char*)buff + bufsz;
+
+ route = route_head_alloc();
+ route_add_head(route);
+
+ head->waypts = le_read32(&head->waypts);
+
+ while (count < head->waypts) {
+ int len;
+
+ /* after version 6 we've seen data with different header length */
+ /* now we try to find the next pair of names in buff */
+
+ while (1) {
+ len = *cin;
+ if ((cin + 120) > cend) {
+ cin = NULL;
+ break;
+ }
+ if ((cin + len < cend) && /* within buff ? */
+ (cin[len + 3] == 0xff) && /* 0xff before next length byte ? */
+ (cin[len + 4] == len) && /* wide string of same length ? */
+ (le_read16(cin + len + 1) == 0xfeff)) {
+ break;
+ }
+ cin++;
+ }
+ if (cin == NULL) {
+ break;
+ }
+
+ wpt = waypt_new();
+
+ len = *cin++; /* length of shortname */
+ cin += len;
+ cin += 3; /* 0xfffeff */
+
+ len = *cin++;
+ wpt->shortname = cet_str_uni_to_utf8((const short*)cin, len);
+ cin += (len * 2); /* seek over wide string */
+ cin += (5 * sizeof(int32_t)); /* five unknown DWORDs */
+
+ /* offs 12 !!!! Latitude int32 LE */
+ /* offs 16 !!!! Longitude int32 LE */
+ wpt->latitude = GPS_Math_Semi_To_Deg(le_read32(cin+12));
+ wpt->longitude = GPS_Math_Semi_To_Deg(le_read32(cin+16));
+
+ cin += (23 * sizeof(int32_t));
+ cin += 3;
+
+#ifdef OLE_DEBUG
+ waypt_add(waypt_dupe(wpt)); /* put to wpt-list to see results if no output is specified */
+#endif
+ route_add_wpt(route, wpt);
+ count++;
+ }
+ }
+
+ if (buff != NULL) {
+ xfree(buff);
+ }
+}
+
+/* registered callbacks */
+
+static void msroute_rd_init(const char* fname)
+{
+ fin = gbfopen(fname, "rb", MYNAME);
+
+ ole_init();
+}
+
+static void msroute_rd_deinit(void)
+{
+ ole_deinit();
+
+ gbfclose(fin);
+}
+
+static void msroute_read(void)
+{
+ msroute_read_journey();
+}
+
+ff_vecs_t msroute_vecs = {
+ ff_type_file,
+ { ff_cap_none, ff_cap_none, ff_cap_read },
+ msroute_rd_init,
+ NULL,
+ msroute_rd_deinit,
+ NULL,
+ msroute_read,
+ NULL,
+ NULL,
+ msroute_args,
+ CET_CHARSET_UTF8, 1 /* CET-REVIEW */
+};
--- /dev/null
+/*
+ Output only format for PalmDoc
+
+ Copyright (C) 2004 Scott Brynen, scott (at) brynen.com
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+ Copyright (C) 2004 Ronald L. Parker, ron@parkrrrr.com
+ Portions from txt2pdbdoc, Copyright (C) 1998 Paul J. Lucas
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+*/
+
+
+#include <ctype.h>
+#include <math.h>
+
+#include "defs.h"
+#if PDBFMTS_ENABLED
+#include "jeeps/gpsmath.h"
+#include "pdbfile.h"
+
+static pdbfile *file_out;
+static short_handle mkshort_handle;
+static short_handle mkshort_bookmark_handle;
+static const char *out_fname;
+
+static char *suppresssep = NULL;
+static char *dbname = NULL;
+static char *bmid = NULL;
+static char *includelogs = NULL;
+
+static int ct;
+static int offset;
+
+static char *palm_encrypt;
+
+#define MYNAME "PALMDOC"
+
+/* constants */
+#define BUFFER_SIZE 4096 /* big enough for uncompressed record */
+#define COMPRESSED 2
+#define COUNT_BITS 3 /* why this value? I don't know */
+#define DISP_BITS 11 /* ditto */
+
+#define DOC_CREATOR 0x52454164 /* "REAd" */
+#define DOC_TYPE 0x54455874 /* "TEXt" */
+#define UNCOMPRESSED 1
+
+struct buffer {
+ unsigned char *data;
+ unsigned len;
+};
+
+#define NEW_BUFFER(b) (b)->data = (unsigned char *)xmalloc( ((b)->len = 0,BUFFER_SIZE) )
+
+static
+arglist_t palmdoc_args[] = {
+ {
+ "nosep", &suppresssep,
+ "No separator lines between waypoints", NULL,
+ ARGTYPE_BOOL, ARG_NOMINMAX
+ },
+ {"dbname", &dbname, "Database name", NULL, ARGTYPE_STRING, ARG_NOMINMAX },
+ {
+ "encrypt", &palm_encrypt, "Encrypt hints with ROT13", NULL,
+ ARGTYPE_BOOL, ARG_NOMINMAX
+ },
+ {
+ "logs", &includelogs,
+ "Include groundspeak logs if present", NULL, ARGTYPE_BOOL, ARG_NOMINMAX
+ },
+ {
+ "bookmarks_short", &bmid, "Include short name in bookmarks",
+ NULL, ARGTYPE_BOOL, ARG_NOMINMAX
+ },
+ ARG_TERMINATOR
+};
+
+static struct buffer buf;
+
+struct doc_record0 { /* 16 bytes total */
+ uint16_t version; /* 1 = plain text, 2 = compressed */
+ uint16_t reserved1;
+ uint32_t doc_size; /* in bytes, when uncompressed */
+ uint16_t num_records; /* PDB header numRecords - 1 */
+ uint16_t rec_size; /* usually RECORD_SIZE_MAX */
+ uint32_t reserved2;
+ uint16_t recsizes[1];
+};
+
+static struct recordsize {
+ int size;
+ struct recordsize *next;
+} *recordsize_tail;
+
+static struct bookmark {
+ int offset;
+ char *text;
+ struct bookmark *next;
+} *bookmark_tail;
+
+struct bookmark_record {
+ char text[16];
+ uint32_t offset;
+};
+
+static void put_byte(struct buffer *b, unsigned char c, int *space)
+{
+ if (*space) {
+ *space = 0;
+ /*
+ ** There is an outstanding space char: see if we can squeeze it
+ ** in with an ASCII char.
+ */
+ if (c >= 0x40 && c <= 0x7F) {
+ b->data[ b->len++ ] = c ^ 0x80;
+ return;
+ }
+ b->data[ b->len++ ] = ' '; /* couldn't squeeze it in */
+ } else if (c == ' ') {
+ *space = 1;
+ return;
+ }
+
+ if ((c >= 1 && c <= 8) || c >= 0x80) {
+ b->data[ b->len++ ] = '\1';
+ }
+
+ b->data[ b->len++ ] = c;
+}
+
+static unsigned char * mem_find(unsigned char *t, int t_len, unsigned char *m, int m_len)
+{
+ register int i;
+ for (i = t_len - m_len + 1; i > 0; --i, ++t)
+ if (*t == *m && !memcmp(t, m, m_len)) {
+ return t;
+ }
+ return 0;
+}
+
+
+static void pd_compress(struct buffer *b)
+{
+
+ unsigned i, j;
+ int space = 0;
+
+ unsigned char *buf_orig;
+ unsigned char *p; /* walking test hit; works up on successive matches */
+ unsigned char *p_prev;
+ unsigned char *head; /* current test string */
+ unsigned char *tail; /* 1 past the current test buffer */
+ unsigned char *end; /* 1 past the end of the input buffer */
+
+ p = p_prev = head = buf_orig = b->data;
+ tail = head + 1;
+ end = b->data + b->len;
+
+ NEW_BUFFER(b);
+ b->len = 0;
+
+ /* loop, absorbing one more char from the input buffer on each pass */
+ while (head != end) {
+ /* establish where the scan can begin */
+ if (head - p_prev > ((1 << DISP_BITS)-1)) {
+ p_prev = head - ((1 << DISP_BITS)-1);
+ }
+
+ /* scan in the previous data for a match */
+ p = mem_find(p_prev, tail - p_prev, head, tail - head);
+
+ /* on a mismatch or end of buffer, issued codes */
+ if (!p || p == head || tail - head > (1 << COUNT_BITS) + 2
+ || tail == end
+ ) {
+ /* issued the codes */
+ /* first, check for short runs */
+ if (tail - head < 4) {
+ put_byte(b, *head++, &space);
+ } else {
+ unsigned dist = head - p_prev;
+ unsigned compound = (dist << COUNT_BITS)
+ + tail - head - 4;
+
+ /* for longer runs, issue a run-code */
+ /* issue space char if required */
+ if (space) {
+ b->data[ b->len++ ] = ' ';
+ space = 0;
+ }
+
+ b->data[ b->len++ ] = 0x80 + (compound >> 8);
+ b->data[ b->len++ ] = compound & 0xFF;
+ head = tail - 1;/* and start again */
+ }
+ p_prev = buf_orig; /* start search again */
+ } else {
+ p_prev = p; /* got a match */
+ }
+
+ /* when we get to the end of the buffer, don't inc past the */
+ /* end; this forces the residue chars out one at a time */
+ if (tail != end) {
+ ++tail;
+ }
+ }
+ xfree(buf_orig);
+
+ if (space) {
+ b->data[ b->len++ ] = ' '; /* add left-over space */
+ }
+
+ /* final scan to merge consecutive high chars together */
+ for (i = j = 0; i < b->len; ++i, ++j) {
+ b->data[ j ] = b->data[ i ];
+
+ /* skip run-length codes */
+ if (b->data[ j ] >= 0x80 && b->data[ j ] < 0xC0) {
+ b->data[ ++j ] = b->data[ ++i ];
+ }
+
+ /* if we hit a high char marker, look ahead for another */
+ else if (b->data[ j ] == '\1') {
+ b->data[ j + 1 ] = b->data[ i + 1 ];
+ while (i + 2 < b->len &&
+ b->data[ i + 2 ] == 1 && b->data[ j ] < 8
+ ) {
+ b->data[ j ]++;
+ b->data[ j + b->data[ j ] ] = b->data[ i + 3 ];
+ i += 2;
+ }
+ j += b->data[ j ];
+ ++i;
+ }
+ }
+ b->len = j;
+}
+
+static void write_header(void)
+{
+
+ int recs = ct-1;
+ struct doc_record0 *rec0;
+ --ct;
+
+ rec0 = (struct doc_record0*) xcalloc(1, sizeof(struct doc_record0)+(ct-1)*sizeof(short));
+ be_write16(&rec0->version, COMPRESSED);
+ be_write16(&rec0->reserved1, 0);
+ be_write32(&rec0->doc_size, offset);
+ be_write16(&rec0->num_records, ct);
+ be_write16(&rec0->rec_size, 4096);
+ be_write32(&rec0->reserved2, 0);
+ while (recs) {
+ struct recordsize *oldrec = recordsize_tail;
+ be_write16(&rec0->recsizes[recs], oldrec->size);
+ recordsize_tail = oldrec->next;
+ xfree(oldrec);
+ --recs;
+ }
+
+ pdb_write_rec(file_out, 0, 0, 0, (void *)rec0, sizeof(struct doc_record0) + sizeof(short)*(ct-1));
+
+ xfree(rec0);
+}
+
+static void write_bookmarks(void)
+{
+ struct bookmark *oldmark = NULL;
+ struct bookmark_record rec;
+
+ struct bookmark *newtail = NULL;
+
+ /* reverse the bookmark list */
+ while (bookmark_tail) {
+ oldmark = bookmark_tail;
+ bookmark_tail = oldmark->next;
+ oldmark->next = newtail;
+ newtail = oldmark;
+ }
+ bookmark_tail = newtail;
+
+ ct++;
+ while (bookmark_tail) {
+ oldmark = bookmark_tail;
+ bookmark_tail = oldmark->next;
+
+ be_write32(&rec.offset, oldmark->offset);
+ memset(rec.text, 0, 16);
+ strncpy(rec.text, oldmark->text, 16);
+
+ pdb_write_rec(file_out, 0, 0, ct++, (void *)&rec, sizeof(struct bookmark_record));
+
+ xfree(oldmark);
+ }
+}
+
+static void commit_buffer(void)
+{
+
+ struct recordsize *newrec = (struct recordsize*) xcalloc(1, sizeof(struct recordsize));
+ newrec->next = recordsize_tail;
+ newrec->size = buf.len;
+ recordsize_tail = newrec;
+
+ pd_compress(&buf);
+
+ pdb_write_rec(file_out, 0, 0, ct++, (void *)buf.data, buf.len);
+}
+
+static void create_bookmark(char *bmtext)
+{
+ struct bookmark *newmark = (struct bookmark *) xcalloc(1, sizeof(struct bookmark));
+ newmark->next = bookmark_tail;
+ newmark->offset = offset;
+ newmark->text = bmtext;
+ bookmark_tail = newmark;
+}
+
+static void docprintf(int maxlen, const char *format, ...)
+{
+
+ char *txt = NULL;
+ char *txt2 = NULL;
+ va_list list;
+ int newlen;
+ int partlen;
+
+ txt = (char *) xmalloc(maxlen);
+
+ va_start(list, format);
+ newlen = vsprintf(txt, format, list);
+
+ txt2 = txt;
+ offset += newlen;
+ while (txt2 && *txt2) {
+ /* append to buffer what we can */
+ partlen = BUFFER_SIZE-1-buf.len;
+ if (buf.len + newlen + 1 > BUFFER_SIZE) {
+ strncpy((char *) buf.data+buf.len, txt2, partlen);
+ buf.data[BUFFER_SIZE-1] = '\0';
+ txt2 += partlen;
+ newlen -= partlen;
+ buf.len = BUFFER_SIZE-1;
+ commit_buffer();
+ NEW_BUFFER(&buf);
+ } else {
+ strcpy((char *) buf.data+buf.len, txt2);
+ buf.len += newlen;
+ txt2 = NULL;
+ }
+ }
+
+ xfree(txt);
+}
+
+static void docfinish()
+{
+ commit_buffer();
+ write_header();
+ write_bookmarks();
+}
+
+static void
+wr_init(const char *fname)
+{
+ file_out = pdb_create(fname, MYNAME);
+ out_fname = fname;
+
+ mkshort_handle = mkshort_new_handle();
+ mkshort_bookmark_handle = mkshort_new_handle();
+ ct = 1;
+ offset = 1;
+ recordsize_tail = NULL;
+ bookmark_tail = NULL;
+ NEW_BUFFER(&buf);
+}
+
+static void
+wr_deinit(void)
+{
+ pdb_close(file_out);
+ mkshort_del_handle(&mkshort_handle);
+ mkshort_del_handle(&mkshort_bookmark_handle);
+
+ if (dbname) {
+ xfree(dbname);
+ dbname = NULL;
+ }
+}
+
+static void
+palmdoc_disp(const waypoint *wpt)
+{
+ int latint, lonint;
+ char tbuf[1024];
+ time_t tm = wpt->GetCreationTime().toTime_t();
+ int32 utmz;
+ double utme, utmn;
+ char utmzc;
+ char *bm;
+ fs_xml *fs_gpx = NULL;
+
+ char bookmarktext[17];
+
+ if (bmid) {
+ char * s = mkshort_from_wpt(mkshort_bookmark_handle, wpt);
+ sprintf(bookmarktext, "%6s:%9s",
+ wpt->shortname?wpt->shortname:"",s);
+ xfree(s);
+ } else {
+ char * s = mkshort_from_wpt(mkshort_bookmark_handle, wpt);
+ sprintf(bookmarktext, "%16s", s);
+ xfree(s);
+ }
+
+ bm = xstrdup(bookmarktext);
+ create_bookmark(bm);
+
+ lonint = abs((int) wpt->longitude);
+ latint = abs((int) wpt->latitude);
+
+ GPS_Math_WGS84_To_UTM_EN(wpt->latitude, wpt->longitude,
+ &utme, &utmn, &utmz, &utmzc);
+
+ if (tm == 0) {
+ tm = time(NULL);
+ }
+ strftime(tbuf, sizeof(tbuf), "%d-%b-%Y", localtime(&tm));
+
+ docprintf(300, "%-16s %c%d %06.3f %c%d %06.3f (%d%c %6.0f %7.0f)",
+ (global_opts.synthesize_shortnames) ? mkshort_from_wpt(mkshort_handle, wpt) : wpt->shortname,
+ wpt->latitude < 0 ? 'S' : 'N', abs(latint), 60.0 * (fabs(wpt->latitude) - latint),
+ wpt->longitude < 0 ? 'W' : 'E', abs(lonint), 60.0 * (fabs(wpt->longitude) - lonint),
+ utmz, utmzc, utme, utmn);
+ if (wpt->altitude != unknown_alt) {
+ docprintf(100, " alt: %1.1f", wpt->altitude);
+ }
+ docprintf(10, "\n");
+ if (strcmp(wpt->description, wpt->shortname)) {
+ docprintf(10+strlen(wpt->description), "%s\n", wpt->description);
+ }
+ if (wpt->gc_data->terr) {
+
+ docprintf(100, "%s/%s\n", gs_get_cachetype(wpt->gc_data->type),
+ gs_get_container(wpt->gc_data->container));
+
+ if (!wpt->gc_data->desc_short.utfstring.isEmpty()) {
+ char *stripped_html = strip_html(&wpt->gc_data->desc_short);
+ docprintf(10+strlen(stripped_html), "\n%s\n", stripped_html);
+ xfree(stripped_html);
+ }
+ if (!wpt->gc_data->desc_long.utfstring.isEmpty()) {
+ char *stripped_html = strip_html(&wpt->gc_data->desc_long);
+ docprintf(10+strlen(stripped_html), "\n%s\n", stripped_html);
+ xfree(stripped_html);
+ }
+ if (!wpt->gc_data->hint.isEmpty()) {
+ char *hint = NULL;
+ if (palm_encrypt) {
+ hint = rot13(wpt->gc_data->hint);
+ } else {
+ hint = xstrdup(wpt->gc_data->hint.toUtf8().data());
+ }
+ docprintf(10+strlen(hint), "\nHint: %s\n", hint);
+ xfree(hint);
+ }
+ } else if (wpt->notes && (!wpt->description || strcmp(wpt->notes,wpt->description))) {
+ docprintf(10+strlen(wpt->notes), "%s\n", wpt->notes);
+ }
+
+ fs_gpx = NULL;
+ if (includelogs) {
+ fs_gpx = (fs_xml *)fs_chain_find(wpt->fs, FS_GPX);
+ }
+
+ if (fs_gpx && fs_gpx->tag) {
+ xml_tag *root = fs_gpx->tag;
+ xml_tag *curlog = NULL;
+ xml_tag *logpart = NULL;
+ curlog = xml_findfirst(root, "groundspeak:log");
+ while (curlog) {
+ time_t logtime = 0;
+ struct tm *logtm = NULL;
+ docprintf(10, "\n");
+
+ logpart = xml_findfirst(curlog, "groundspeak:type");
+ if (logpart) {
+ docprintf(10+strlen(logpart->cdata), "%s by ", logpart->cdata);
+ }
+
+ logpart = xml_findfirst(curlog, "groundspeak:finder");
+ if (logpart) {
+ docprintf(10+strlen(logpart->cdata), "%s on ", logpart->cdata);
+ }
+
+ logpart = xml_findfirst(curlog, "groundspeak:date");
+ if (logpart) {
+ logtime = xml_parse_time(logpart->cdata).toTime_t();
+ logtm = localtime(&logtime);
+ if (logtm) {
+ docprintf(15,
+ "%2.2d/%2.2d/%4.4d\n",
+ logtm->tm_mon+1,
+ logtm->tm_mday,
+ logtm->tm_year+1900
+ );
+ }
+ }
+
+ logpart = xml_findfirst(curlog, "groundspeak:log_wpt");
+ if (logpart) {
+ char *coordstr = NULL;
+ float lat = 0;
+ int latdeg = 0;
+ float lon = 0;
+ int londeg = 0;
+ coordstr = xml_attribute(logpart, "lat");
+ if (coordstr) {
+ lat = atof(coordstr);
+ }
+ coordstr = xml_attribute(logpart, "lon");
+ if (coordstr) {
+ lon = atof(coordstr);
+ }
+ latdeg = abs(lat);
+ londeg = abs(lon);
+
+ docprintf(30,
+ "%c %d\xb0 %.3f' %c %d\xb0 %.3f'\n",
+
+ lat < 0 ? 'S' : 'N', latdeg, 60.0 * (fabs(lat) - latdeg),
+ lon < 0 ? 'W' : 'E', londeg, 60.0 * (fabs(lon) - londeg)
+ );
+ }
+
+ logpart = xml_findfirst(curlog, "groundspeak:text");
+ if (logpart) {
+ char *encstr = NULL;
+ char *s = NULL;
+ int encoded = 0;
+ encstr = xml_attribute(logpart, "encoded");
+ encoded = (toupper(encstr[0]) != 'F');
+
+ if (palm_encrypt && encoded) {
+ s = rot13(logpart->cdata);
+ } else {
+ s = xstrdup(logpart->cdata);
+ }
+
+ docprintf(5+strlen(s), "%s", s);
+ xfree(s);
+ }
+
+ docprintf(10, "\n");
+ curlog = xml_findnext(root, curlog, "groundspeak:log");
+ }
+ }
+ if (! suppresssep) {
+ docprintf(50, "---------------------------\n");
+ } else {
+ docprintf(10, "\n");
+ }
+}
+
+static void
+data_write(void)
+{
+ if (dbname) {
+ strncpy(file_out->name, dbname, PDB_DBNAMELEN);
+ } else {
+ strncpy(file_out->name, out_fname, PDB_DBNAMELEN);
+ }
+ file_out->name[PDB_DBNAMELEN-1] = 0;
+ file_out->attr = PDB_FLAG_BACKUP;
+ file_out->ctime = file_out->mtime = current_time().toTime_t() + 2082844800U;
+ file_out->type = DOC_TYPE;
+ file_out->creator = DOC_CREATOR;
+ file_out->version = 1;
+
+ if (! suppresssep) {
+ docprintf(50, "---------------------------\n");
+ }
+ setshort_length(mkshort_handle, 20);
+ setshort_length(mkshort_bookmark_handle, 16-(bmid?7:0));
+ setshort_whitespace_ok(mkshort_bookmark_handle, 0);
+ waypt_disp_all(palmdoc_disp);
+
+ docfinish();
+}
+
+
+ff_vecs_t palmdoc_vecs = {
+ ff_type_file,
+ { ff_cap_write, ff_cap_none, ff_cap_none},
+ NULL,
+ wr_init,
+ NULL,
+ wr_deinit,
+ NULL,
+ data_write,
+ NULL,
+ palmdoc_args,
+ CET_CHARSET_ASCII, 0 /* CET-REVIEW */
+};
+
+
+#endif
--- /dev/null
+/*
+ Support for PathAway Palm Database,
+ Copyright (C) 2005-2006 Olaf Klein, o.b.klein@gpsbabel.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+*/
+
+/*
+ remarks:
+
+ The german release 3.0 of PathAway violates the PathAway standards:
+ * N.. .... O.. .... instead of N.. .... E.. ....
+ * date is formatted in DDMMYYYY instead of YYYYMMDD
+
+ Release 4.x store only numeric coordinates and uses a six-number date.
+
+ Modified by by Andrei Boros <slackware@andrix.ro> 2008-11-07
+ * added information about database vehicle icon
+ * Pathaway 4.x can handle invalid date/time and date format apparently
+ has changed slightly between revisions :
+ 131502.29 26102008 = HHMMSS.MS DDMMYYYY
+ * work around errors reading date/time information
+ (real life data collected by Pathaway sometimes has the date/time field
+ contain some missing/invalid data. This information can be safely
+ ignored most of the time. So far gpsbabel stopped processing files
+ when encountering such invalid data)
+ - date/time field may contain one or more spaces between fields
+ - date/time field may start with one or more spaces
+ - date/time field may contain invalid characters -> ignore
+ - invalid or missing date/time -> ignore
+ - only time may be present (some older versions of Pathaway 4)
+
+ (this is still incomplete, but solved most of my problems when converting
+ pathaway .pdb files)
+
+*/
+
+
+#include <ctype.h>
+#include <math.h>
+
+#include "defs.h"
+#if PDBFMTS_ENABLED
+#include "csv_util.h"
+#include "pdbfile.h"
+#include "strptime.h"
+
+#define MYNAME "pathaway"
+
+#define PPDB_MAGIC_TRK 0x55735472 /* UsTr */
+#define PPDB_MAGIC_WPT 0x506f4c69 /* PoLi */
+#define PPDB_MAGIC 0x4b6e5772 /* KwNr */
+
+#define VEHICLE_LEN 100
+
+static pdbfile *file_in, *file_out;
+static char *fname_out;
+static short_handle mkshort_handle;
+static gpsdata_type ppdb_type;
+static unsigned char german_release = 0;
+static char *datefmt;
+static int ct;
+static int warn_ = 0;
+
+typedef struct ppdb_appdata {
+ unsigned char reservedA[274]; /* all 0 */
+ unsigned char dirtyFlag;
+ unsigned char dataBaseSubType; /* 0 = Track, 1 = Route */
+ short int dbAttributes; /* 0 */
+ char vehicleStr[VEHICLE_LEN];
+ unsigned char reservedB[100]; /* all 0 */
+} ppdb_appdata_t;
+
+#define PPDB_APPINFO_SIZE sizeof(struct ppdb_appdata)
+static ppdb_appdata_t *appinfo;
+
+static char *opt_dbname = NULL;
+static char *opt_dbicon = NULL;
+static char *opt_deficon = NULL;
+static char *opt_snlen = NULL;
+static char *opt_date = NULL;
+
+static arglist_t ppdb_args[] = {
+ {"date", &opt_date, "Read/Write date format (i.e. DDMMYYYY)", NULL, ARGTYPE_STRING, ARG_NOMINMAX},
+ {"dbname", &opt_dbname, "Database name", NULL, ARGTYPE_STRING, ARG_NOMINMAX},
+ {"dbicon", &opt_dbicon, "Database vehicle icon name", NULL, ARGTYPE_STRING, ARG_NOMINMAX},
+ {"deficon", &opt_deficon, "Default icon name", NULL, ARGTYPE_STRING, ARG_NOMINMAX},
+ {"snlen", &opt_snlen, "Length of generated shortnames", "10", ARGTYPE_INT, "1", NULL },
+ ARG_TERMINATOR
+};
+
+/*#undef PPDB_DEBUG*/
+#define PPDB_DEBUG 1
+
+#if PPDB_DEBUG
+static void
+internal_debug1(const char *filename, int fileline)
+{
+ static int ct=1;
+ printf("DBG(%d): file %s, line %d: ", ct++, filename, fileline);
+}
+static void
+internal_debug2(const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ vprintf(format, args);
+ puts("");
+ va_end(args);
+}
+#define DBG(args) internal_debug1(__FILE__, __LINE__);internal_debug2 args
+#else
+#define DBG(args) ;
+#endif
+
+
+#define CHECK_INP(i, j, k, l) is_fatal((i != j), "Error in data structure (in %s? Value is : %s).", (k), (l))
+
+/*
+ * utilities
+ */
+
+static
+char *ppdb_strcat(char *dest, const char *src, const char *def, int *size)
+{
+ int len;
+ char *res;
+ const char *tmp;
+
+ tmp = src;
+ if (tmp == NULL) {
+ tmp = def;
+ if (tmp == NULL) {
+ return dest;
+ }
+ }
+ if (*tmp == '\0') {
+ return dest;
+ }
+
+ len = strlen(dest) + strlen(tmp) + 1;
+ if (len > *size) {
+ *size = len;
+ res = (char*) xrealloc(dest, *size);
+ } else {
+ res = dest;
+ }
+ strcat(res, tmp);
+ return res;
+}
+
+#define STR_POOL_SIZE 16 /* !!! any power of 2 !!! */
+
+static char *str_pool[STR_POOL_SIZE];
+static size_t str_pool_s[STR_POOL_SIZE];
+static int str_poolp = -1;
+
+static
+void str_pool_init(void)
+{
+ int i;
+ for (i = 0; i < STR_POOL_SIZE; i++) {
+ str_pool[i] = NULL;
+ str_pool_s[i] = 0;
+ }
+}
+
+static
+void str_pool_deinit(void)
+{
+ int i;
+
+ for (i = 0; i < STR_POOL_SIZE; i++)
+ if (str_pool_s[i] != 0) {
+ xfree(str_pool[i]);
+ str_pool[i] = NULL;
+ str_pool_s[i] = 0;
+ }
+}
+
+static
+char *str_pool_get(size_t size)
+{
+ char *tmp;
+
+ str_poolp = ((str_poolp + 1) & (STR_POOL_SIZE - 1));
+ tmp = str_pool[str_poolp];
+
+ if (str_pool_s[str_poolp] == 0) {
+ tmp = (char*) xmalloc(size);
+ } else if (str_pool_s[str_poolp] < size) {
+ tmp = (char*) xrealloc(tmp, size);
+ } else {
+ return tmp;
+ }
+
+ str_pool[str_poolp] = tmp;
+ str_pool_s[str_poolp] = size;
+
+ return tmp;
+}
+
+static
+char *str_pool_getcpy(const char *src, const char *def)
+{
+ char *res;
+
+ if (src == NULL) {
+ src = def;
+ if (src == NULL) {
+ src = "";
+ }
+ }
+ res = str_pool_get(strlen(src) + 1);
+ strcpy(res, src);
+
+ return res;
+}
+
+/*
+ * decoding/formatting functions
+ */
+
+static
+char *ppdb_fmt_float(const double val)
+{
+ char *str = str_pool_get(32);
+ char *c;
+ snprintf(str, 32, "%.8f", val);
+ c = str + strlen(str) - 1;
+ while ((c > str) && (*c == '0')) {
+ *c = '\0';
+ c--;
+ if (*c == '.') {
+ c++;
+ *c = '0';
+ break;
+ }
+ }
+ return str;
+}
+
+static
+char *ppdb_fmt_degrees(char dir, double val)
+{
+ char *str = str_pool_get(32);
+ int deg = fabs(val);
+ double min = 60.0 * (fabs(val) - deg);
+ char *tmp;
+
+ snprintf(str, 31, "%c%0*d %.8f", dir, (deg > 99) ? 3 : 2, deg, min);
+
+ tmp = str + strlen(str) - 1; /* trim trailing nulls */
+ while ((tmp > str) && (*tmp == '0')) {
+ *tmp = '\0';
+ tmp--;
+ if (*tmp == '.') {
+ tmp++;
+ *tmp = '0';
+ break;
+ }
+ }
+ return str;
+}
+
+static
+double ppdb_decode_coord(const char *str)
+{
+ double val;
+ int deg;
+ char dir;
+
+ if (*str < 'A') { /* only numeric */
+ CHECK_INP(1, sscanf(str,"%lf", &val), "decode_coord(1) DD.dddd", str);
+ return val;
+ } else {
+ const char *tmp;
+
+ if (*str == 'O') {
+ german_release = 1;
+ }
+
+ tmp = strchr(str, ' ');
+ if ((tmp) && (tmp - str < 5)) {
+ CHECK_INP(3, sscanf(str,"%c%d %lf", &dir, °, &val), "decode_coord(2) DD MM.mmm", str);
+ val = deg + (val / 60.0);
+ } else {
+ CHECK_INP(2, sscanf(str,"%c%lf", &dir, &val), "decode_coord(3) DD.dddd", str);
+ }
+ if ((dir == 'S') || (dir == 'W')) {
+ val = -val;
+ }
+ }
+ return val;
+}
+
+static
+int ppdb_decode_tm(char *str, struct tm *tm)
+{
+ int msec, d1, d2, d3, d4;
+ int year;
+ int temp=0;
+ char *cx;
+
+ str = lrtrim(str); /* time field may start/end with spaces, drop them */
+
+ if (*str == '\0') {
+ if (global_opts.debug_level > 0) {
+ warning(MYNAME ": Time value missing, reseting to 0\n");
+ warn_ = 1;
+ }
+ return 0; /* empty time field */
+ }
+
+ if (strchr(str, '.')) { /* time in hhmmss.ms */
+ CHECK_INP(4, sscanf(str, "%02d%02d%02d.%d",
+ &tm->tm_hour, &tm->tm_min, &tm->tm_sec, &msec),
+ "decode_tm(1) hhmmss.ss", str);
+ } else if (sscanf(str,"%06d",&temp)==1)
+ /* WORKAROUND read time info only if a valid 6 digit string found */
+ {
+ CHECK_INP(3, sscanf(str, "%02d%02d%02d",
+ &tm->tm_hour, &tm->tm_min, &tm->tm_sec),
+ "decode_tm(2) hhmmss", str);
+ } else {
+ if (global_opts.debug_level > 0) {
+ warning(MYNAME ": Invalid time value, reseting to 0\n");
+ warn_ = 1;
+ }
+ return 0; /* WORKAROUND maybe invalid time, just ignore it and continue */
+ }
+ cx = strchr(str, ' ');
+
+ if (cx == NULL) {
+ if (global_opts.debug_level > 0) {
+ warning(MYNAME ": Date value missing, reseting to 0\n");
+ warn_ = 1;
+ }
+ return 0; /* empty date field */
+ }
+
+ cx = lrtrim(cx);
+ if (*cx == '\0') {
+ if (global_opts.debug_level > 0) {
+ warning(MYNAME ": Date value missing, found only spaces, reseting to 0\n");
+ warn_ = 1;
+ }
+ return 0; /* empty date field */
+ }
+
+ if (datefmt) {
+ struct tm tm2;
+
+ if (NULL == strptime(cx, datefmt, &tm2)) {
+ fatal(MYNAME ": Unable to convert date '%s' using format '%s' (%s)!\n", cx, datefmt, opt_date);
+ }
+
+ tm->tm_year = tm2.tm_year + 1900;
+ tm->tm_mon = tm2.tm_mon + 1;
+ tm->tm_mday = tm2.tm_mday;
+ } else {
+ time_t tnow;
+ struct tm now;
+
+
+ tnow = current_time().toTime_t();
+ now = *localtime(&tnow);
+ now.tm_year += 1900;
+ now.tm_mon++;
+
+ if (strlen(cx) == 8) {
+ CHECK_INP(4, sscanf(cx, "%02d%02d%02d%02d", &d1, &d2, &d3, &d4), "decode_tm(3) invalid date (YYYYMMDD)", cx);
+
+ year = (d1 * 100) + d2;
+ /* the coordinates comes before date and time in
+ the dataset, so the flag "german_release" is set yet. */
+
+ /* next code works for most, except for 19. and 20. of month */
+
+ if ((german_release != 0) || (year < 1980) || (year > now.tm_year)) { /* YYYYMMDD or DDMMYYYY ????? */
+ tm->tm_year = (d3 * 100) + d4;
+ tm->tm_mon = d2;
+ tm->tm_mday = d1;
+ } else {
+ tm->tm_year = (d1 * 100) + d2;
+ tm->tm_mon = d3;
+ tm->tm_mday = d4;
+ }
+ } else if (strlen(cx) == 6) {
+ CHECK_INP(3, sscanf(cx, "%02d%02d%02d", &d1, &d2, &d3), "decode_tm(3) invalid date (DDMMYY)", cx);
+ if (d3 < 1970) { /* Usual Y2K interpretation */
+ year = d3 + 2000;
+ } else {
+ year = d3 + 1900;
+ }
+
+ /* I don't know how a german release handles this
+ * so for now I will assume only DDMMYY if date has 6 digits
+ */
+ tm->tm_year = year;
+ tm->tm_mon = d2;
+ tm->tm_mday = d1;
+ } else { /* date string is neither 8 nor 6 digits */
+ printf(MYNAME ": Date from first record is %s.\n", cx);
+ printf(MYNAME ": Please use option 'date' to specify how this is formatted.\n");
+ fatal(MYNAME ": (... -i pathaway,date=DDMMYY ...)\n");
+ }
+ }
+ return 1;
+}
+
+static
+int ppdb_read_wpt(route_head *head, int isRoute)
+{
+ char *data, *str;
+ double altfeet;
+ struct tm tm;
+
+ while (pdb_read_rec(file_in, NULL, NULL, NULL, (void **)&data) >= 0) {
+ waypoint *wpt_tmp = waypt_new();
+ int line = 0;
+ char *tmp = data;
+
+ /* Print the whole input record. All input records are printed before processing. */
+ if (global_opts.debug_level >= 5) {
+ DBG(("\n\
+--- BEGIN Input data record -----------------------------------------------\n\
+%s\n\
+--- END Input data record -------------------------------------------------\n",data));
+ }
+
+ while ((str = csv_lineparse(tmp, ",", "\"", line++))) {
+ tmp = NULL;
+ switch (line) {
+ case 1: /* latitude */
+ wpt_tmp->latitude = ppdb_decode_coord(str);
+ break;
+ case 2: /* longitude */
+ wpt_tmp->longitude = ppdb_decode_coord(str);
+ break;
+ case 3: /* altitude */
+ if (*str != '\0') {
+ CHECK_INP(1, sscanf(str, "%lf", &altfeet), "altitude", str);
+ if (altfeet != -9999) {
+ wpt_tmp->altitude = FEET_TO_METERS(altfeet);
+ }
+ }
+ break;
+ case 4: /* time and date (optional) */
+ memset(&tm, 0, sizeof(tm));
+ if (ppdb_decode_tm(str, &tm)) {
+ tm.tm_year -= 1900;
+ tm.tm_mon--;
+ wpt_tmp->SetCreationTime(mkgmtime(&tm));
+ }
+ break;
+ case 5: /* name */
+ if (*str != '\0') {
+ wpt_tmp->shortname = xstrdup(str);
+ }
+ break;
+ case 6: /* icon */
+ if (*str != '\0') {
+ wpt_tmp->icon_descr = str;
+ }
+ break;
+ case 7: /* notes */
+ if (*str != '\0') {
+ wpt_tmp->notes = xstrdup(str);
+ }
+ break;
+
+ }
+ }
+
+ /* Print the whole input record, should a warning be triggered.
+ * Use warning() here instead of DBG() to print the data record
+ * right after the warning is issued.
+ */
+ if (warn_ && (global_opts.debug_level > 1) && (global_opts.debug_level < 5)) {
+ warning("Faulty input data record : %s\n",data);
+ warn_ = 0;
+ }
+
+ if (head && isRoute) {
+ route_add_wpt(head, wpt_tmp);
+ } else if (head) {
+ track_add_wpt(head, wpt_tmp);
+ } else {
+ waypt_add(wpt_tmp);
+ }
+
+ }
+ return 0;
+}
+
+/* ============================================================================================
+ * &&& gobal callbacks &&&
+ * ----------------------------------------------------------------------------------------- */
+
+static void ppdb_rd_init(const char *fname)
+{
+ str_pool_init();
+ file_in = pdb_open(fname, MYNAME);
+ ct = 0;
+
+ if (opt_date) {
+ datefmt = convert_human_date_format(opt_date);
+ } else {
+ datefmt = NULL;
+ }
+}
+
+static void ppdb_rd_deinit(void)
+{
+ pdb_close(file_in);
+ str_pool_deinit();
+ if (datefmt) {
+ xfree(datefmt);
+ }
+}
+
+static void ppdb_read(void)
+{
+ ppdb_appdata_t *info = NULL;
+ route_head *track_head, *route_head;
+ const char *descr = NULL;
+
+ if (file_in->creator != PPDB_MAGIC) { /* identify the database */
+ fatal(MYNAME ": Not a PathAway pdb file.\n");
+ }
+
+ if (file_in->version != 3) { /* Currently we support only version 3 */
+ fatal(MYNAME ": This file is from an untested version (%d) of PathAway and is unsupported.\n", file_in->version);
+ }
+
+ if ((file_in->appinfo_len > 0) && (file_in->appinfo != NULL)) {
+ info = (ppdb_appdata_t *) file_in->appinfo;
+ descr = info->vehicleStr;
+ }
+ switch (file_in->type) {
+ case PPDB_MAGIC_TRK:
+ ppdb_type = trkdata; /* as default */
+ if (info != NULL) {
+ switch (info->dataBaseSubType) {
+ case 0:
+ ppdb_type = trkdata;
+ break;
+ case 1:
+ ppdb_type = rtedata;
+ break;
+ default:
+ fatal(MYNAME": Invalid database subtype.\n");
+ }
+ }
+ break;
+
+ case PPDB_MAGIC_WPT:
+ ppdb_type = wptdata;
+ break;
+
+ default:
+ fatal(MYNAME ": It looks like a PathAway pdb, but has no gps magic.\n");
+ }
+
+ switch (ppdb_type) {
+ case trkdata:
+ track_head = route_head_alloc();
+ track_add_head(track_head);
+ track_head->rte_name = xstrdup(file_in->name);
+ ppdb_read_wpt(track_head, 0);
+ break;
+ case rtedata:
+ route_head = route_head_alloc();
+ route_add_head(route_head);
+ route_head->rte_name = xstrdup(file_in->name);
+ ppdb_read_wpt(route_head, 1);
+ break;
+ case wptdata:
+ case unknown_gpsdata:
+ ppdb_read_wpt(NULL, 0);
+ break;
+ case posndata:
+ fatal(MYNAME ": Realtime positioning not supported.\n");
+ break;
+ }
+}
+
+/* ============================================================================================
+ * PPDB: Write support
+ * -------------------------------------------------------------------------------------------*/
+
+static void ppdb_wr_init(const char *fname)
+{
+ int len;
+
+ fname_out = xstrdup(fname);
+ str_pool_init();
+ file_out = pdb_create(fname, MYNAME);
+ mkshort_handle = mkshort_new_handle();
+ ct = 0;
+ appinfo = NULL;
+
+ if (global_opts.synthesize_shortnames != 0) {
+ len = atoi(opt_snlen);
+ setshort_length(mkshort_handle, len);
+ setshort_mustupper(mkshort_handle, 1);
+ setshort_badchars(mkshort_handle, ",");
+ setshort_whitespace_ok(mkshort_handle, 0);
+ }
+ if (opt_date) {
+ char *c = convert_human_date_format(opt_date);
+ xasprintf(&datefmt, "%s %s", "%H%M%S", c);
+ xfree(c);
+ } else {
+ datefmt = xstrdup("%H%M%S %Y%m%d");
+ }
+}
+
+static void ppdb_wr_deinit(void)
+{
+ mkshort_del_handle(&mkshort_handle);
+ pdb_close(file_out);
+ str_pool_deinit();
+ xfree(fname_out);
+ if (datefmt) {
+ xfree(datefmt);
+ }
+ if (appinfo) {
+ xfree(appinfo);
+ }
+}
+
+/*
+ * ppdb_write_wpt: callback for waypoint output
+ */
+
+#define REC_SIZE 128
+
+static void ppdb_write_wpt(const waypoint *wpt)
+{
+ char *buff, *tmp;
+ char latdir, longdir;
+ int len;
+ struct tm tm;
+
+ buff = (char *) xcalloc(REC_SIZE, 1);
+
+ if (wpt->latitude < 0) {
+ latdir = 'S';
+ } else {
+ latdir = 'N';
+ }
+ if (wpt->longitude < 0) {
+ longdir = 'W';
+ } else {
+ longdir = 'E';
+ }
+ /* 1 latitude,
+ 2 longitude */
+
+ snprintf(buff, REC_SIZE, "%s,%s,",
+ ppdb_fmt_degrees(latdir, wpt->latitude),
+ ppdb_fmt_degrees(longdir, wpt->longitude)
+ );
+
+ len = REC_SIZE; /* we have coordinates in buff, now optional stuff */
+ /* 3 altitude */
+
+ if (fabs(wpt->altitude) < 9999.0) {
+ tmp = str_pool_get(32);
+ snprintf(tmp, 32, "%s", ppdb_fmt_float(METERS_TO_FEET(wpt->altitude)));
+ buff = ppdb_strcat(buff, tmp, NULL, &len);
+ }
+ buff = ppdb_strcat(buff, ",", NULL, &len);
+ /* 4 time, date */
+
+ if (wpt->creation_time.isValid()) {
+ tmp = str_pool_get(20);
+ const time_t tt = wpt->GetCreationTime().toTime_t();
+ tm = *gmtime(&tt);
+ strftime(tmp, 20, datefmt, &tm);
+ buff = ppdb_strcat(buff, tmp, NULL, &len);
+ }
+ buff = ppdb_strcat(buff, ",", NULL, &len);
+ /* 5 name */
+
+ if (global_opts.synthesize_shortnames != 0) {
+ tmp = mkshort_from_wpt(mkshort_handle, wpt);
+ DBG(("shortname %s from %s", tmp, wpt->shortname));
+ } else {
+ tmp = str_pool_getcpy(wpt->shortname, "");
+ while (strchr(tmp, ',') != NULL) {
+ *strchr(tmp, ',') = '.';
+ }
+ }
+ buff = ppdb_strcat(buff, tmp, "", &len);
+
+ buff = ppdb_strcat(buff, ",", NULL, &len);
+ /* 6 icon */
+
+ tmp = str_pool_getcpy(wpt->icon_descr.toUtf8().data(), opt_deficon); /* point icon or deficon from options */
+ buff = ppdb_strcat(buff, tmp, NULL, &len);
+ buff = ppdb_strcat(buff, ",", NULL, &len);
+ /* 7 description */
+
+ tmp = str_pool_getcpy(wpt->description, "");
+ if (strchr(tmp, ',') != NULL) {
+ buff = ppdb_strcat(buff, "\"", NULL, &len);
+ while (strchr(tmp, '"') != NULL) {
+ *strchr(tmp, '"') = '\'';
+ }
+ buff = ppdb_strcat(buff, tmp, NULL, &len);
+ buff = ppdb_strcat(buff, "\"", NULL, &len);
+ } else {
+ buff = ppdb_strcat(buff, tmp, "", &len);
+ }
+
+ len = strlen(buff) + 1;
+ pdb_write_rec(file_out, 0, 0, ct++, buff, len);
+
+ xfree(buff);
+}
+
+/*
+ * track and route write callbacks
+ */
+
+static void ppdb_write(void)
+{
+
+ if (opt_dbname) {
+ strncpy(file_out->name, opt_dbname, PDB_DBNAMELEN);
+ }
+
+ file_out->attr = PDB_FLAG_BACKUP;
+ file_out->ctime = file_out->mtime = current_time().toTime_t() + 2082844800U;
+ file_out->creator = PPDB_MAGIC;
+ file_out->version = 3;
+
+ /* Waypoint target does use vehicleStr from appinfo block
+ * Actually, all 3 types have vehicle information.
+ * if (global_opts.objective != wptdata) / * Waypoint target do not need appinfo block * /
+ * {
+ */
+ appinfo = (ppdb_appdata_t *) xcalloc(1, sizeof(*appinfo));
+ file_out->appinfo = (void *)appinfo;
+ file_out->appinfo_len = PPDB_APPINFO_SIZE;
+ /* }
+ */
+ if (opt_dbicon != NULL) {
+ strncpy(appinfo->vehicleStr, opt_dbicon, VEHICLE_LEN);
+ }
+
+ switch (global_opts.objective) { /* Only one target is possible */
+ case wptdata:
+ case unknown_gpsdata:
+ if (opt_dbname == NULL) {
+ strncpy(file_out->name, "PathAway Waypoints", PDB_DBNAMELEN);
+ }
+ file_out->type = PPDB_MAGIC_WPT;
+ waypt_disp_all(ppdb_write_wpt);
+ break;
+ case trkdata:
+ if (opt_dbname == NULL) {
+ strncpy(file_out->name, "PathAway Track", PDB_DBNAMELEN);
+ }
+ file_out->type = PPDB_MAGIC_TRK;
+ appinfo->dataBaseSubType = 0;
+ track_disp_all(NULL, NULL, ppdb_write_wpt);
+ break;
+ case rtedata:
+ if (opt_dbname == NULL) {
+ strncpy(file_out->name, "PathAway Route", PDB_DBNAMELEN);
+ }
+ file_out->type = PPDB_MAGIC_TRK;
+ appinfo->dataBaseSubType = 1;
+ route_disp_all(NULL, NULL, ppdb_write_wpt);
+ break;
+ case posndata:
+ fatal(MYNAME ": Realtime positioning not supported.\n");
+ break;
+ }
+}
+
+
+ff_vecs_t ppdb_vecs = {
+ ff_type_file,
+ FF_CAP_RW_ALL,
+ ppdb_rd_init,
+ ppdb_wr_init,
+ ppdb_rd_deinit,
+ ppdb_wr_deinit,
+ ppdb_read,
+ ppdb_write,
+ NULL,
+ ppdb_args,
+ CET_CHARSET_ASCII, 0 /* CET-REVIEW */
+};
+#endif
--- /dev/null
+/*
+
+ Minimum support for Palm/OS database files
+ Copyright (C) 2007 Olaf Klein, o.b.klein@gpsbabel.org
+
+ Written after study the Coldsync project
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+
+#if PDBFMTS_ENABLED
+
+#include "gbfile.h"
+#include "pdbfile.h"
+#include <stdio.h>
+#include <string.h>
+
+
+#define MYNAME "pdbfile"
+
+static void
+pdb_invalid_file(const pdbfile *pdb_in, const char *fmt, ...)
+{
+ char buff[128];
+ va_list args;
+
+ va_start(args, fmt);
+ vsnprintf(buff, sizeof(buff), fmt, args);
+ buff[sizeof(buff)-1] = '0';
+
+ warning(MYNAME ": %s\n", buff);
+ fatal(MYNAME ": Invalid or unsupported file (%s).\n", pdb_in->file->name);
+}
+
+/* try to read to EOF (avoid determining file-size) */
+
+static void *
+pdb_read_tail(gbfile *fin, int32_t *size)
+{
+ int count;
+ char buff[256];
+ char *res = NULL;
+ int bytes = 0;
+
+ while ((count = gbfread(buff, 1, sizeof(buff), fin))) {
+
+ if (!res) {
+ res = (char *) xmalloc(count);
+ memcpy(res, buff, count);
+ } else {
+ res = (char*) xrealloc(res, bytes + count);
+ memcpy(&res[bytes], buff, count);
+ }
+ bytes += count;
+ }
+ if (res) {
+ res = (char*) xrealloc(res, bytes + 1);
+ } else {
+ res = (char*) xmalloc(1);
+ }
+ res[bytes] = '\0';
+
+ if (size) {
+ *size = bytes;
+ }
+ return (void *)res;
+}
+
+static void
+pdb_load_data(pdbfile *fin)
+{
+ uint16_t i, ct;
+ pdbrec_t *last_rec;
+ uint32_t offs;
+ pdbrec_t *rec;
+
+ /* load the header */
+ gbfread(fin->name, 1, PDB_DBNAMELEN, fin->file);
+ fin->name[PDB_DBNAMELEN] = '\0';
+
+ fin->attr = gbfgetuint16(fin->file);
+ fin->version = gbfgetuint16(fin->file);
+ fin->ctime = gbfgetuint32(fin->file);
+ fin->mtime = gbfgetuint32(fin->file);
+ fin->btime = gbfgetuint32(fin->file);
+ fin->revision = gbfgetuint32(fin->file);
+ fin->appinfo_offs = gbfgetint32(fin->file);
+ fin->index_offs = gbfgetuint32(fin->file);
+ fin->type = gbfgetuint32(fin->file);
+ fin->creator = gbfgetuint32(fin->file);
+ fin->uid = gbfgetuint32(fin->file);
+
+ if (fin->appinfo_offs < 0) {
+ pdb_invalid_file(fin, "Invalid application data offset (%0xh)", fin->appinfo_offs);
+ }
+ if (fin->index_offs < 0) {
+ pdb_invalid_file(fin, "Invalid index offset (%0xh)", fin->index_offs);
+ }
+
+#if 0
+ fprintf(stderr, "%s: dbname \"%s\"\n", MYNAME, fin->name);
+ fprintf(stderr, "%s: attr %-8x\n", MYNAME, fin->attr);
+ fprintf(stderr, "%s: creator %-8x\n", MYNAME, fin->creator);
+ fprintf(stderr, "%s: type %-8x\n", MYNAME, fin->type);
+ fprintf(stderr, "%s: ver %-8u\n", MYNAME, fin->version);
+ fprintf(stderr, "%s: app-ofs %-8u\n", MYNAME, fin->appinfo_offs);
+ fprintf(stderr, "%s: index-ofs %-8u\n", MYNAME, fin->index_offs);
+#endif
+ /* ID = */ (void) gbfgetuint32(fin->file);
+ ct = fin->rec_ct = gbfgetint16(fin->file);
+ if (ct >= 0x7FFF) {
+ warning(MYNAME ": Probably invalid number of records (%0d)\n", fin->rec_ct);
+ }
+
+ offs = 78;
+
+ last_rec = NULL;
+ for (i = 0; i < ct; i++) {
+ pdbrec_t *rec;
+
+ rec = (pdbrec_t*) xcalloc(1, sizeof(*rec));
+ if (fin->attr & PDB_FLAG_RESOURCE) {
+ (void) gbfgetuint32(fin->file); /* type */
+ rec->id = gbfgetint16(fin->file);
+ rec->offs = gbfgetuint32(fin->file);
+ if ((int32_t)rec->offs < 0) {
+ pdb_invalid_file(fin, "Invalid offset to record (%0d, id = %d)", rec->offs, rec->id);
+ }
+ } else {
+ uint32_t x;
+
+ rec->offs = gbfgetint32(fin->file);
+ x = gbfgetuint32(fin->file);
+ rec->id = x & 0x0ffff;
+ rec->category = (x >> 24) & 0x0f;
+ rec->flags = (x >> 24) & 0xf0;
+ if ((int32_t)rec->offs < 0) {
+ pdb_invalid_file(fin, "Invalid offset to resource record (%0d, id = %d)", rec->offs, rec->id);
+ }
+ }
+
+ if (last_rec == NULL) {
+ fin->rec_list = rec;
+ } else {
+ last_rec->next = rec;
+ }
+ last_rec = rec;
+ }
+
+ offs += (ct * 8);
+ last_rec = fin->rec_list;
+
+ if (fin->appinfo_offs != 0) {
+ uint32_t top;
+
+ /* seek to application info offset */
+ while (offs < fin->appinfo_offs) {
+ (void)gbfgetc(fin->file);
+ offs++;
+ }
+
+ /* determine the length of application info */
+ if (fin->index_offs != 0) {
+ top = fin->index_offs;
+ } else {
+ top = 0x7FFFFFFU;
+ }
+ if (last_rec && (last_rec->offs < top)) {
+ top = last_rec->offs;
+ }
+
+ if (top != 0x7FFFFFFU) {
+ fin->appinfo = xmalloc(top - offs);
+ fin->appinfo_len = gbfread(fin->appinfo, 1, top - offs, fin->file);
+ offs += fin->appinfo_len;
+ } else {
+ int32_t size;
+ fin->appinfo = pdb_read_tail(fin->file, &size);
+ fin->appinfo_len = size;
+ offs += size;
+ }
+ }
+
+ for (rec = fin->rec_list; rec; rec = rec->next) {
+ /* seek to current record */
+ while (offs < rec->offs) {
+ (void) gbfgetc(fin->file);
+ offs++;
+ }
+ if (rec->next) {
+ rec->size = (int32_t)rec->next->offs - (int32_t)offs;
+ if (rec->size > 0) {
+ rec->data = (char*) xmalloc(rec->size);
+ rec->size = gbfread(rec->data, 1, rec->size, fin->file);
+ offs += rec->size;
+ } else if (rec->size < 0) {
+ pdb_invalid_file(fin, "Wrong data size in record with id %d.\n", rec->id);
+ }
+ } else {
+ rec->data = (char*) pdb_read_tail(fin->file, &rec->size);
+ offs += rec->size;
+ }
+ }
+}
+
+pdbfile *
+pdb_open(const char *filename, const char *module)
+{
+ pdbfile *res;
+
+ res = (pdbfile*) xcalloc(1, sizeof(*res));
+ res->file = gbfopen_be(filename, "rb", module);
+ res->mode = 1;
+
+ pdb_load_data(res);
+ pdb_rewind(res);
+
+ return res;
+}
+
+int
+pdb_read_rec_by_id(pdbfile *fin, const uint32_t rec_id, uint8_t *flags, uint8_t *category, void **data)
+{
+ pdbrec_t *rec;
+
+ for (rec = fin->rec_list; rec; rec = rec->next) {
+ if (rec->id == rec_id) {
+ if (data) {
+ *data = rec->data;
+ }
+ if (flags) {
+ *flags = rec->flags;
+ }
+ if (category) {
+ *category = rec->category;
+ }
+ return rec->size;
+ }
+ }
+ return -1;
+}
+
+pdbfile *
+pdb_create(const char *filename, const char *module)
+{
+ pdbfile *res;
+
+ res = (pdbfile*) xcalloc(1, sizeof(*res));
+ strncpy(res->name, "Palm/OS Database", PDB_DBNAMELEN);
+ res->file = gbfopen_be(filename, "wb", module);;
+ res->mode = 2;
+
+ return res;
+}
+
+void
+pdb_write_rec(pdbfile *fout, const uint8_t flags, const uint8_t category, const uint32_t rec_id, const void *data, const uint32_t size)
+{
+ pdbrec_t *rec, *cur;
+
+ rec = (pdbrec_t*) xcalloc(1, sizeof(*rec));
+ rec->category = category;
+ rec->flags = category;
+ rec->id = rec_id;
+ rec->size = size;
+ if (size > 0) {
+ rec->data = (char*) xmalloc(size);
+ memcpy(rec->data, data, size);
+ }
+
+ /* insert rec into rec_list sorted by id */
+ cur = fout->rec_list;
+ if (cur == NULL) {
+ fout->rec_list = rec;
+ } else {
+ pdbrec_t *prev = NULL;
+
+ while (cur) {
+ if (rec_id < cur->id) {
+ rec->next = cur;
+ if (prev == NULL) {
+ fout->rec_list = rec;
+ } else {
+ prev->next = rec;
+ }
+ break;
+ } else if (rec_id == cur->id) { /* Overwrite record with id ... */
+ rec->next = cur->next;
+ if (prev == NULL) {
+ fout->rec_list = rec;
+ } else {
+ prev->next = rec;
+ }
+ if (cur->data) {
+ xfree(cur->data);
+ }
+ xfree(cur);
+ cur = rec;
+ break;
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+ if (! cur) {
+ if (prev == NULL) {
+ fout->rec_list = rec;
+ } else {
+ prev->next = rec;
+ }
+ }
+ }
+ fout->rec_ct++;
+}
+
+/* all data was buffered, write now to file */
+
+static void
+pdb_flush(pdbfile *file)
+{
+ pdbrec_t *rec;
+ gbfile *fout = file->file;
+ int len, offs;
+
+ offs = 78;
+ file->index_offs = 0;
+ offs += (file->rec_ct * 8);
+
+ offs += 2;
+
+ if (file->appinfo && (file->appinfo_len > 0)) {
+ file->appinfo_offs = offs;
+ offs += file->appinfo_len;
+ } else {
+ file->appinfo_offs = 0;
+ }
+
+ rec = file->rec_list;
+ while (rec) { /* prepare data records */
+ rec->offs = offs;
+ offs += rec->size;
+ rec = rec->next;
+ }
+
+ len = strlen(file->name);
+ gbfwrite(file->name, 1, len, fout);
+ while (len++ < PDB_DBNAMELEN) {
+ gbfputc(0, fout);
+ }
+
+ gbfputuint16(file->attr, fout);
+ gbfputuint16(file->version, fout);
+ gbfputuint32(file->ctime, fout);
+ gbfputuint32(file->mtime, fout);
+ gbfputuint32(file->btime, fout);
+ gbfputuint32(file->revision, fout);
+ gbfputuint32(file->appinfo_offs, fout);
+ gbfputuint32(file->index_offs, fout);
+ gbfputuint32(file->type, fout);
+ gbfputuint32(file->creator, fout);
+ gbfputuint32(file->uid, fout);
+
+ gbfputuint32(0, fout); /* ? ID ? */
+ gbfputuint16(file->rec_ct, fout);
+
+ for (rec = file->rec_list; rec; rec = rec->next) {
+ uint32_t attr;
+
+ gbfputint32(rec->offs, fout);
+ attr = (rec->category & 0x0f) | (rec->flags & 0xf0);
+ gbfputint32((rec->id & 0x0ffffff) | (attr << 24), fout);
+ }
+ gbfputint16(0, fout);
+
+ if (file->appinfo && (file->appinfo_len > 0)) {
+ gbfwrite(file->appinfo, 1, file->appinfo_len, fout);
+ }
+
+ for (rec = file->rec_list; rec; rec = rec->next) {
+ if (rec->size > 0) {
+ gbfwrite(rec->data, 1, rec->size, fout);
+ }
+ }
+}
+
+void
+pdb_close(pdbfile *file)
+{
+ pdbrec_t *rec;
+
+ if (! file) {
+ return;
+ }
+
+ if (file->mode & 2) {
+#if 0
+ /* this can be done later */
+ if (gpsbabel_time == 0) { /* !!! We are in testo !!! */
+ file->ctime = 0; /* (now we also can do a bincompare) */
+ file->mtime = 0;
+ file->btime = 0;
+ }
+#endif
+ pdb_flush(file);
+ }
+
+ gbfclose(file->file);
+
+ if ((file->mode & 1) && file->appinfo) {
+ xfree(file->appinfo);
+ }
+
+ rec = file->rec_list;
+ while (rec) {
+ pdbrec_t *tmp = rec;
+ rec = rec->next;
+
+ if (tmp->data) {
+ xfree(tmp->data);
+ }
+ xfree(tmp);
+ }
+ xfree(file);
+}
+
+int
+pdb_eof(pdbfile *fin)
+{
+ return (fin->rec_curr) ? 0 : 1;
+}
+
+int
+pdb_read_rec(pdbfile *fin, uint8_t *flags, uint8_t *category, uint32_t *rec_id, void **data)
+{
+ if (pdb_eof(fin)) {
+ return -1;
+ } else {
+ pdbrec_t *rec = fin->rec_curr;
+ fin->rec_curr = rec->next;
+
+ if (data) {
+ *data = rec->data;
+ }
+ if (flags) {
+ *flags = rec->flags;
+ }
+ if (category) {
+ *category = rec->category;
+ }
+ if (rec_id) {
+ *rec_id = rec->id;
+ }
+
+ return rec->size;
+ }
+}
+
+void
+pdb_rewind(pdbfile *fin)
+{
+ fin->rec_curr = fin->rec_list;
+}
+
+#endif
--- /dev/null
+/*
+ PocketStreets 2002 Pushpin Files
+ Contributed to gpsbabel by Alex Mottram (geo_alexm at cox-internet.com)
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+#include "cet.h"
+#include "cet_util.h"
+#include <ctype.h>
+#include "grtcirc.h"
+
+#define MYNAME "PSP"
+
+#define MAXPSPSTRINGSIZE 256
+#define MAXPSPOUTPUTPINS 8192 /* Any more points than this is ludicrous */
+
+static gbfile *psp_file_in;
+static gbfile *psp_file_out;
+static short_handle mkshort_handle;
+
+#define psp_fread(b,s,m,f) gbfread((b),(s),(m),f)
+#define psp_fread_double(f) gbfgetdbl(f)
+#define psp_fwrite_double(v,f) gbfputdbl((v),f)
+
+/* ToDo: move the code inside to CET library */
+static void
+psp_write_str(const char *str)
+{
+ if (str && *str) {
+ short *unicode;
+ int len;
+
+ /* convert UTF-8 string into a unicode sequence */
+ /* not perfect, but enough for us */
+ unicode = cet_str_any_to_uni(str, global_opts.charset, &len);
+ if (len > MAXPSPSTRINGSIZE) {
+ len = MAXPSPSTRINGSIZE;
+ }
+ gbfputc((unsigned char)len, psp_file_out);
+ if (len) {
+ gbfwrite(unicode, 2, len, psp_file_out);
+ }
+
+ xfree(unicode);
+ } else {
+ gbfputc(0, psp_file_out);
+ }
+}
+
+/* ToDo: move the code inside to CET library */
+static char *
+psp_read_str(gbfile *fin)
+{
+ int len;
+ int16_t *buff;
+ char *res;
+
+ len = (unsigned char)gbfgetc(fin);
+ if (len == 0) {
+ return NULL;
+ }
+
+ buff = (int16_t*) xmalloc(len * sizeof(*buff));
+ gbfread(buff, sizeof(*buff), len, fin);
+ res = cet_str_uni_to_utf8(buff, len);
+ xfree(buff);
+
+ return res;
+}
+
+/* Implement the grid in ascii art... This makes a bit of sense if you stand
+ on a point over the north pole and look down on the earth.
+
+-180 -90 0 90 180
+------------------------------------ /\
+| 0x03 U|S 0x02 U|k 0x00 | 0x01 | 90
+|--------|--------|--------|--------| 0
+| 0x07 | 0x06 | 0x04 | 0x05 | -90
+------------------------------------ \/
+*/
+static
+char grid_byte(double lat, double lon)
+{
+ char c = 0x00;
+
+ if ((lon >= 0.0) && (lon < 90.0)) {
+ if (lat >= 0.0) {
+ c = 0x00;
+ } else {
+ c = 0x04;
+ }
+ } else if (lon >= 90.0) {
+ if (lat >= 0.0) {
+ c = 0x01;
+ } else {
+ c = 0x05;
+ }
+ } else if ((lon < 0.0) && (lon >= -90.0)) {
+ if (lat >= 0.0) {
+ c = 0x02;
+ } else {
+ c = 0x06;
+ }
+ } else if (lon < -90.0) {
+ if (lat >= 0.0) {
+ c = 0x03;
+ } else {
+ c = 0x07;
+ }
+ }
+
+ return (c);
+}
+
+void decode_psp_coordinates(double * lat, double * lon, const char lonbyte)
+{
+ /* This is some sort of 1/2 Polar, 1/2 Cartesian coordinate mess in */
+ /* the pin file. I really shouldn't have to do this. Zones 02 and 03 */
+ /* work properly. The other zones are assumptions based on 02 and 03 */
+
+ if ((lonbyte == 0x02) || (lonbyte == 0x06)) {
+ /* one step west of zero longitude */
+ if (*lon > 0.0) {
+ *lon *= -1.0;
+ }
+ } else if ((lonbyte == 0x03) || (lonbyte == 0x07)) {
+ /* two steps west of zero longitude */
+ if (*lon > 0.0) {
+ *lon -= 180.0;
+ }
+ } else if ((lonbyte == 0x00) || (lonbyte == 0x04)) {
+ /* one step east of zero longitude */
+ if (*lon < 0.0) {
+ *lon *= -1.0;
+ }
+ } else if ((lonbyte == 0x01) || (lonbyte == 0x05)) {
+ /* two steps east of zero longitude */
+ if (*lon < 0.0) {
+ *lon += 180.0;
+ }
+ }
+}
+
+static int
+valid_psp_header(char * header)
+{
+ char header_bytes[] = { 0x31, 0x6E, 0x69, 0x50 }; /* 1niP <stop> */
+
+ return (memcmp(header_bytes, header, 4));
+
+}
+
+static void
+psp_rd_init(const char *fname)
+{
+ psp_file_in = gbfopen_le(fname, "rb", MYNAME);
+}
+
+static void
+psp_rd_deinit(void)
+{
+ gbfclose(psp_file_in);
+}
+
+static void
+psp_wr_init(const char *fname)
+{
+ psp_file_out = gbfopen_le(fname, "wb", MYNAME);
+ mkshort_handle = mkshort_new_handle();
+}
+
+static void
+psp_wr_deinit(void)
+{
+ mkshort_del_handle(&mkshort_handle);
+ gbfclose(psp_file_out);
+}
+
+static void
+psp_read(void)
+{
+ char buff[MAXPSPSTRINGSIZE + 1];
+ double radians;
+ double lat, lon;
+ waypoint *wpt_tmp;
+ short int pincount;
+ short int pindex;
+ char gridbyte = 0x00;
+ char *tmp;
+
+ /* 32 bytes - file header */
+ psp_fread(&buff[0], 1, 32, psp_file_in);
+
+ if (valid_psp_header(buff) != 0) {
+ fatal(MYNAME ": input file does not appear to be a valid .PSP file.\n");
+ }
+
+ pincount = le_read16(&buff[12]);
+
+ while (pincount--) {
+ wpt_tmp = waypt_new();
+
+ wpt_tmp->altitude = unknown_alt;
+
+ /* offset 0x20 - 0x21 pin index */
+ psp_fread(&pindex, 1, 2, psp_file_in);
+
+ /* offset 0x22 - 0x23 */
+ psp_fread(&buff[0], 1, 2, psp_file_in);
+
+ /* offset 0x24 */
+ /* 1 byte, the grid byte - needed for sign corrections later*/
+ psp_fread(&gridbyte, 1, 1, psp_file_in);
+
+ /* 8 bytes - latitude in radians */
+ radians = psp_fread_double(psp_file_in);
+ lat = DEG(radians);
+
+ /* 8 bytes - longitude in radians */
+ radians = psp_fread_double(psp_file_in);
+ lon = DEG(radians);
+
+ /* since we don't know the origin of this PSP file, we use */
+ /* the grid byte adjust longitude, if necessary, mimicing */
+ /* the behavior of pocketstreets correcting the data. This */
+ /* does not correct the fact that points in eastern US are */
+ /* written with the wrong coordinates by S&T. (MS bug) */
+
+ decode_psp_coordinates(&lat, &lon, gridbyte);
+
+ wpt_tmp->latitude = lat;
+ wpt_tmp->longitude = lon;
+
+ /* 1 byte - pin display properties */
+ psp_fread(&buff[0], 1, 1, psp_file_in);
+
+ /* 3 bytes - unknown */
+ psp_fread(&buff[0], 1, 3, psp_file_in);
+
+ /* 1 bytes - icon (values: 0x00 - 0x27) */
+ psp_fread(&buff[0], 1, 1, psp_file_in);
+
+ /* 3 bytes - unknown */
+ psp_fread(&buff[0], 1, 3, psp_file_in);
+
+ wpt_tmp->shortname = psp_read_str(psp_file_in);
+ wpt_tmp->description = psp_read_str(psp_file_in);
+ tmp = psp_read_str(psp_file_in); /* (address?) */
+ if (tmp) {
+ xfree(tmp);
+ }
+
+ waypt_add(wpt_tmp);
+ }
+}
+
+static void
+psp_waypt_pr(const waypoint *wpt)
+{
+ double lon, lat;
+ char tbuf[64];
+ char c;
+ static short int pindex = 0;
+ char *shortname;
+ char *description;
+
+ if ((! wpt->shortname) || (global_opts.synthesize_shortnames)) {
+ if (wpt->description) {
+ if (global_opts.synthesize_shortnames) {
+ shortname = mkshort_from_wpt(mkshort_handle, wpt);
+ } else {
+ shortname = xstrdup(wpt->description);
+ }
+ } else {
+ /* no description available */
+ shortname = xstrdup("");
+ }
+ } else {
+ shortname = xstrdup(wpt->shortname);
+ }
+
+ if (! wpt->description) {
+ if (shortname) {
+ description = xstrdup(shortname);
+ } else {
+ description = xstrdup("");
+ }
+ } else {
+ description = xstrdup(wpt->description);
+ }
+
+ /* convert lat/long back to radians */
+ lat = RAD(wpt->latitude);
+ lon = RAD(wpt->longitude);
+
+ pindex++;
+ /* 2 bytes - pin index */
+ gbfputint16(pindex, psp_file_out);
+
+ /* 2 bytes - null bytes */
+ gbfputint16(0, psp_file_out);
+
+
+ /* set the grid byte */
+ c = grid_byte(wpt->latitude,
+ wpt->longitude);
+
+ /* since the grid byte matches with what pocketstreets does to */
+ /* input files, our output appears identical to a pin file that */
+ /* has already been processed and corrected by pocketstreets. */
+ /* Due to the grid and signs, it'll look different than one that */
+ /* comes straight from S&T. */
+
+ /* the grid byte */
+ gbfwrite(&c, 1, 1, psp_file_out);
+
+ /* 8 bytes - latitude/radians */
+ psp_fwrite_double(lat, psp_file_out);
+
+ /* 8 bytes - longitude/radians */
+ psp_fwrite_double(lon, psp_file_out);
+
+ /* 1 byte - pin properties */
+ c = 0x14; /* display pin name on, display notes on. 0x04 = no notes */
+ gbfwrite(&c, 1, 1, psp_file_out);
+
+ memset(tbuf, '\0', sizeof(tbuf));
+
+ /* 3 unknown bytes */
+ gbfwrite(tbuf, 1, 3, psp_file_out);
+
+ /* 1 icon byte 0x00 = PIN */
+ gbfwrite(tbuf, 1, 1, psp_file_out);
+
+ /* 3 unknown bytes */
+ gbfwrite(tbuf, 1, 3, psp_file_out); /* 3 junk */
+
+ psp_write_str(shortname);
+ psp_write_str(description);
+
+ /* just for the hell of it, we'll scrap the third string. */
+ psp_write_str("");
+
+ xfree(shortname);
+ xfree(description);
+}
+
+static void
+psp_write(void)
+{
+ short int s;
+ unsigned char header_bytes[] = { 0x31, 0x6E, 0x69, 0x50, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ /* the header: */
+ /* 31 6E 69 50 20 00 00 00 08 00 00 00 11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */
+ /* offset 0x0C - 0x0D = 2 byte pin count */
+
+ s = waypt_count();
+
+ if (global_opts.synthesize_shortnames) {
+ setshort_length(mkshort_handle, 32);
+ setshort_whitespace_ok(mkshort_handle, 1);
+ }
+
+ if (s > MAXPSPOUTPUTPINS) {
+ fatal(MYNAME ": attempt to output too many pushpins (%d). The max is %d. Sorry.\n", s, MAXPSPOUTPUTPINS);
+ }
+
+ /* insert waypoint count into header */
+ le_write16(&header_bytes[12], s);
+
+ gbfwrite(header_bytes, 1, 32, psp_file_out);
+
+ waypt_disp_all(psp_waypt_pr);
+}
+
+ff_vecs_t psp_vecs = {
+ ff_type_file,
+ FF_CAP_RW_WPT,
+ psp_rd_init,
+ psp_wr_init,
+ psp_rd_deinit,
+ psp_wr_deinit,
+ psp_read,
+ psp_write,
+ NULL,
+ NULL,
+ CET_CHARSET_UTF8, 1 /* Fixed because of unicode strings in psp files (see psp_read_str / psp_write_str) */
+};
--- /dev/null
+/*
+ Read and write QuoVadis files.
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "quovadis.h"
+
+#if PDBFMTS_ENABLED
+static pdbfile *file_in, *file_out;
+
+static uint8_t* rec_ptr = NULL;
+static uint8_t* current_rec = NULL;
+static int rec_index = 0;
+static int ct;
+static char *dbname = NULL;
+
+static
+arglist_t quovadis_args[] = {
+ {"dbname", &dbname, "Database name", NULL, ARGTYPE_STRING, ARG_NOMINMAX},
+ ARG_TERMINATOR
+};
+
+static struct qv_icon_mapping mapping[] = {
+ { gt_unknown, QUESTION_ICON },
+ { gt_traditional, HOSPITAL_ICON },
+ { gt_multi, DOCUMENT_ICON },
+ { gt_virtual, CAMERA_ICON },
+ { gt_letterbox, MAILBOX_ICON },
+ { gt_event, MEETING_ICON },
+ { gt_suprise, GIFTSHOP_ICON },
+};
+
+#define num_mappings (sizeof(mapping) / sizeof(struct qv_icon_mapping))
+
+static geocache_type icon_to_wpt(int icon_bitmap)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_mappings; i++) {
+ if (icon_bitmap == mapping[i].bitmap_id) {
+ return mapping[i].gc_type;
+ }
+ }
+ return gt_unknown;
+}
+
+static int wpt_to_icon(geocache_type type)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_mappings; i++) {
+ if (type == mapping[i].gc_type) {
+ return mapping[i].bitmap_id;
+ }
+ }
+ return QUESTION_ICON;
+}
+
+static void
+rd_init(const char *fname)
+{
+ file_in = pdb_open(fname, MYNAME);
+}
+
+static void
+rd_deinit(void)
+{
+ pdb_close(file_in);
+ if (dbname) {
+ xfree(dbname);
+ dbname = NULL;
+ }
+}
+
+static void
+wr_init(const char *fname)
+{
+ file_out = pdb_create(fname, MYNAME);
+ ct = 0;
+}
+
+static void
+wr_deinit(void)
+{
+ pdb_close(file_out);
+ if (dbname) {
+ xfree(dbname);
+ dbname = NULL;
+ }
+}
+
+static void
+data_read(void)
+{
+ struct record *rec;
+ pdbrec_t *pdb_rec;
+ int i;
+
+ if (!file_in->rec_list || (file_in->creator != MYCREATOR) || (file_in->type != MYTYPE)) {
+ fatal(MYNAME ": Not a QuoVadis file.\n");
+ }
+
+ /* Ignore the first record, it contains one zero byte */
+ for (pdb_rec = file_in->rec_list->next; pdb_rec; pdb_rec = pdb_rec->next) {
+ int num_recs = pdb_rec->size / sizeof(struct record);
+ for (i = 0; i < num_recs; i++) {
+ waypoint *wpt_tmp;
+
+ wpt_tmp = waypt_new();
+
+ rec = (struct record *)
+ &(pdb_rec->data[i * sizeof(struct record)]);
+
+ wpt_tmp->longitude =
+ (be_read32(&rec->longitude) / 1000000.0) - 180.0;
+ wpt_tmp->latitude =
+ 90.0 - (be_read32(&rec->latitude) / 1000000.0);
+ wpt_tmp->shortname = xstrdup(rec->name);
+
+ waypt_alloc_gc_data(wpt_tmp)->type =
+ icon_to_wpt(be_read16(&rec->icon_bitmap));
+
+ waypt_add(wpt_tmp);
+ }
+ }
+}
+
+
+static void
+quovadis_writewpt(waypoint *wpt)
+{
+ struct record *rec;
+ int i;
+
+ if (current_rec == NULL) {
+ uint8_t dummy = 0;
+
+ pdb_write_rec(file_out, 0, 0, ct++, &dummy, 1);
+
+ current_rec = (uint8_t *) xcalloc(MAXCHUNKSIZE, 1);
+ rec_index = 0;
+ rec_ptr = current_rec;
+ }
+
+ rec = (struct record *) xcalloc(sizeof(*rec),1);
+
+ be_write32(&rec->longitude, (unsigned int)((wpt->longitude +
+ 180.0) * 1000000.0));
+ be_write32(&rec->latitude, (unsigned int)((90.0 - wpt->latitude) * 1000000.0));
+ if (wpt->shortname) {
+ strncpy(rec->name, wpt->shortname, 32);
+ rec->name[31] = '\0';
+ } else {
+ rec->name[0] = '\0';
+ }
+ be_write16(&rec->icon_bitmap, wpt_to_icon(wpt->gc_data->type));
+ be_write32(&rec->note_id, 0);
+ rec->name_scale = DEFAULT_NAME_SCALE;
+ rec->icon_scale = DEFAULT_ICON_SCALE;
+ for (i = 0; i < 7; i++) {
+ rec->reserved[i] = 0;
+ }
+
+ memcpy(rec_ptr, rec, sizeof(*rec));
+ rec_ptr += sizeof(*rec);
+ rec_index += 1;
+ xfree(rec);
+
+ if (rec_index == MAXRECORDS) {
+ fatal(MYNAME ": cannot store more than %lu records at this time.\n",
+ (unsigned long) MAXRECORDS);
+ }
+}
+
+struct hdr {
+ char *wpt_name;
+ waypoint *wpt;
+};
+
+static
+int
+compare(const void *a, const void *b)
+{
+ const struct hdr *wa = (const struct hdr *) a;
+ const struct hdr *wb = (const struct hdr *) b;
+
+ return strcmp(wa->wpt->shortname, wb->wpt->shortname);
+}
+
+static void
+data_write(void)
+{
+ int i, ct = waypt_count();
+ struct hdr *htable, *bh;
+ queue *elem, *tmp;
+ extern queue waypt_head;
+ waypoint *waypointp;
+
+ if (dbname) {
+ strncpy(file_out->name, dbname, PDB_DBNAMELEN);
+ } else {
+ strncpy(file_out->name, "QuoVadisMarkerDB", PDB_DBNAMELEN);
+ }
+ file_out->name[PDB_DBNAMELEN-1] = 0;
+ file_out->attr = PDB_FLAG_BACKUP;
+ file_out->ctime = file_out->mtime = current_time().toTime_t() + 2082844800U;
+ file_out->type = MYTYPE; /* CWpt */
+ file_out->creator = MYCREATOR; /* cGPS */
+ file_out->version = 1;
+
+ /*
+ * All this is to sort by waypoint names before going to QuoVadis.
+ * Turns out plain old strcmp will do the trick...
+ */
+
+ htable = (struct hdr *) xmalloc(ct * sizeof(*htable));
+ bh = htable;
+
+ QUEUE_FOR_EACH(&waypt_head, elem, tmp) {
+ waypointp = (waypoint *) elem;
+ bh->wpt = waypointp;
+ bh->wpt_name = waypointp->shortname;
+ bh ++;
+ }
+ qsort(htable, ct, sizeof(*bh), compare);
+
+ for (i=0; i<ct; i++) {
+ quovadis_writewpt(htable[i].wpt);
+ }
+
+ if (rec_index != 0) {
+ pdb_write_rec(file_out, 0, 0, ct++, current_rec, rec_index * sizeof(struct record));
+ }
+ xfree(current_rec);
+
+ xfree(htable);
+}
+
+
+ff_vecs_t quovadis_vecs = {
+ ff_type_file,
+ FF_CAP_RW_WPT,
+ rd_init,
+ wr_init,
+ rd_deinit,
+ wr_deinit,
+ data_read,
+ data_write,
+ NULL,
+ quovadis_args,
+ CET_CHARSET_ASCII, 0 /* CET-REVIEW */
+};
+#endif
--- /dev/null
+/*
+ Definitions for QuoVadis files.
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+#ifndef __quovadis_h__
+#define __quovadis_h__
+
+#include "defs.h"
+#include "pdbfile.h"
+
+#define MYNAME "QuoVadis"
+#define MYTYPE 0x51564D52 /* QVMR */
+#define MYCREATOR 0x51554F56 /* QUOV */
+
+#define MAXCHUNKSIZE 0x10000 /* 64k Chunk max */
+
+struct record {
+ char name[32];
+ pdb_32 longitude; /* Scaled. (degrees + 180.0) * 1e6 */
+ pdb_32 latitude; /* Scaled. (degrees + 90.0) * 1e6 */
+ pdb_16 icon_bitmap; /* Valid range: 0 - 47 */
+ pdb_32 note_id; /* Global ID of note in NotesDB. Not
+ supported yet */
+ char name_scale; /* Map scale to display the
+ name. Valid range 15-26. 15 =>
+ 18.12 miles, 26 => 46 feet */
+ char icon_scale; /* As above. */
+ unsigned char reserved[8];
+};
+
+struct qv_icon_mapping {
+ const geocache_type gc_type;
+ const int bitmap_id;
+};
+
+/* Icon Types */
+#define QUESTION_ICON 0
+#define RESTARAUNT_ICON 1
+#define BAR_ICON 2
+#define HOTEL_ICON 3
+#define PHONE_ICON 4
+#define HOSPITAL_ICON 5
+#define CHURCH_ICON 6
+#define AIRPORT_ICON 7
+#define TRAIN_ICON 8
+#define BUS_ICON 9
+#define CAR_ICON 10
+#define WRENCH_ICON 11
+#define GASOLINE_ICON 12
+#define PARKING_ICON 13
+#define MAIL_ICON 14
+#define MAILBOX_ICON 15
+#define CLOCK_ICON 16
+#define FLAG_ICON 17
+#define LIBRARY_ICON 18
+#define BUILDINGS_ICON 19
+#define RELIGION_ICON 20
+#define DOCUMENT_ICON 21
+#define ANIMAL_ICON 22
+#define CAMERA_ICON 23
+#define MOVIE_ICON 24
+#define MUSIC_ICON 25
+#define MEETING_ICON 26
+#define RESTROOM_ICON 27
+#define FAMILY_ICON 28
+#define TELEVISION_ICON 29
+#define SAILING_ICON 30
+#define GOLF_ICON 31
+#define WORKOUT_ICON 32
+#define CYCLING_ICON 33
+#define JOGGING_ICON 34
+#define CAMPING_ICON 35
+#define WATER_ICON 36
+#define FOREST_ICON 37
+#define GIFTSHOP_ICON 38
+#define BABY_ICON 39
+#define LOVE_ICON 40
+#define CEMETARY_ICON 41
+#define COMPUTER_ICON 42
+#define MONEY_ICON 43
+#define LEFT_ARROW_ICON 44
+#define RIGHT_ARROW_ICON 45
+#define DOWN_ARROW_ICON 46
+#define UP_ARROW_ICON 47
+
+/* Scale Values */
+#define SCALE_18_12MI 15
+#define SCALE_9_06MI 16
+#define SCALE_4_53MI 17
+#define SCALE_2_26MI 18
+#define SCALE_1_13MI 19
+#define SCALE_0_56MI 20
+#define SCALE_0_28MU 21
+#define SCALE_747FT 22
+#define SCALE_373FT 23
+#define SCALE_186FT 24
+#define SCALE_93FT 25
+#define SCALE_46FT 26
+
+#define MAXRECORDS (MAXCHUNKSIZE / sizeof(struct record))
+/*#define MAXRECORDS 100*/
+#define DEFAULT_ICON_BITMAP QUESTION_ICON
+#define DEFAULT_NAME_SCALE SCALE_2_26MI
+#define DEFAULT_ICON_SCALE SCALE_18_12MI
+
+#endif
+++ /dev/null
-/*
- Read and write GeocachingPDB files.
-
- Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
-
- */
-
-#include "defs.h"
-#if PDBFMTS_ENABLED
-#include "pdbfile.h"
-
-#define MYNAME "GeocachingDB"
-#define MYTYPE 0x44415441 /* DATA */
-#define MYCREATOR 0x42726174 /* Brat */
-
-#define MAXRECSZ 500 /* This is overkill as the records seem to be around 100
-bytes a piece, but being conservative and dealing
-with realloc issues just doesn't seem worth it. */
-
-typedef enum {
-RECTYPE_TEXT = 0,
-RECTYPE_DATE = 2
-} gcdb_rectype;
-
-struct dbfld {
-char fldname[4];
-pdb_16 fldtype;
-pdb_16 fldlen;
-};
-
-struct dbrec {
-pdb_16 nflds;
-struct dbfld dbfld[1];
-};
-
-static pdbfile* file_in, *file_out;
-static const char* out_fname;
-static int ct;
-
-static char* tbuf = NULL;
-static char* tbufp = NULL;
-
-static void
-rd_init(const char* fname)
-{
-file_in = pdb_open(fname, MYNAME);
-}
-
-static void
-rd_deinit(void)
-{
-pdb_close(file_in);
-}
-
-static void
-wr_init(const char* fname)
-{
-file_out = pdb_create(fname, MYNAME);
-out_fname = fname;
-ct = 0;
-}
-
-static void
-wr_deinit(void)
-{
-pdb_close(file_out);
-if (tbuf) {
-xfree(tbuf);
-}
-}
-
-static void
-data_read(void)
-{
-pdbrec_t* pdb_rec;
-
-if ((file_in->creator != MYCREATOR) || (file_in->type != MYTYPE)) {
-fatal(MYNAME ": Not a GeocachingDB file.\n");
-}
-
-for (pdb_rec = file_in->rec_list; pdb_rec; pdb_rec=pdb_rec->next) {
-waypoint* wpt = waypt_new();
-struct dbrec* rec = (struct dbrec*) pdb_rec->data;
-int nflds;
-int length;
-int type;
-int i;
-char* recdata;
-int lat_dir = 0;
-int lat_deg = 0;
-float lat_min = 0.0;
-int lon_dir = 0;
-int lon_deg = 0;
-float lon_min = 0.0;
-
-nflds = be_read16(&rec->nflds);
-recdata = (char*) &rec->dbfld[nflds];
-
-for (i = 0; i < nflds; i++) {
-length = (unsigned short) be_read16(&rec->dbfld[i].fldlen);
-type = be_read16(&rec->dbfld[i].fldtype);
-
-switch (type) {
-case RECTYPE_TEXT: /* Text */
-if (!strncmp("gcid", rec->dbfld[i].fldname,4)) {
-wpt->shortname = xstrdup(recdata);
-} else if (!strncmp("gcna", rec->dbfld[i].fldname,4)) {
-wpt->description = xstrdup(recdata);
-} else if (!strncmp("lat0", rec->dbfld[i].fldname,4)) {
-lat_dir = *recdata == 'N' ? 1 : -1;
-} else if (!strncmp("lat1", rec->dbfld[i].fldname,4)) {
-lat_deg = atoi(recdata);
-} else if (!strncmp("lat2", rec->dbfld[i].fldname,4)) {
-lat_min = atof(recdata);
-}
-if (!strncmp("lon0", rec->dbfld[i].fldname,4)) {
-lon_dir = *recdata == 'E' ? 1 : -1;
-} else if (!strncmp("lon1", rec->dbfld[i].fldname,4)) {
-lon_deg = atoi(recdata);
-} else if (!strncmp("lon2", rec->dbfld[i].fldname,4)) {
-lon_min = atof(recdata);
-} else if (!strncmp("take", rec->dbfld[i].fldname,4)) {
-wpt->notes = xstrappend(wpt->notes, " Took ");
-wpt->notes = xstrappend(wpt->notes, recdata);
-} else if (!strncmp("left", rec->dbfld[i].fldname,4)) {
-wpt->notes = xstrappend(wpt->notes, " Left ");
-wpt->notes = xstrappend(wpt->notes, recdata);
-} else if (!strncmp("diff", rec->dbfld[i].fldname,4)) {
-waypt_alloc_gc_data(wpt)->diff = 10 * atof(recdata);
-} else if (!strncmp("terr", rec->dbfld[i].fldname,4)) {
-waypt_alloc_gc_data(wpt)->terr = 10 * atof(recdata);
-}
-break;
-#if 0
-/* This really is the date of the find,
-* not the cache creation date.
-*/
-case RECTYPE_DATE:
-if (!strncmp("date", rec->dbfld[i].fldname,4)) {
-time_t tm;
-tm = be_read32(recdata) * 24 * 3600;
-tm -= EPOCH_1904;
-wpt->SetCreationTime(tm);
-warning("date %d\n", tm);
-}
-break;
-#endif
-}
-recdata += (length + 1) & (~1);
-}
-wpt->latitude = lat_dir * (lat_deg + lat_min/60);
-wpt->longitude = lon_dir * (lon_deg + lon_min/60);
-waypt_add(wpt);
-}
-}
-
-
-static int
-gcdb_add_to_rec(struct dbrec* rec, const char* fldname, gcdb_rectype rectype, const void* data)
-{
-int length;
-static int rec_cnt;
-
-if (!tbuf) {
-tbuf = (char*) xcalloc(MAXRECSZ, 1);
-tbufp = tbuf;
-}
-
-if (fldname == NULL) {
-length = tbufp - tbuf;
-be_write16(&rec->nflds, rec_cnt);
-memcpy(&rec->dbfld[rec_cnt],tbuf, length);
-tbufp = tbuf;
-length += 4 + sizeof(struct dbfld) * rec_cnt;
-rec_cnt = 0;
-return length;
-}
-
-be_write16(&rec->dbfld[rec_cnt].fldtype,rectype);
-strncpy(rec->dbfld[rec_cnt].fldname, fldname, 4);
-
-switch (rectype) {
-case RECTYPE_TEXT:
-length = 1 + strlen((const char*)data);
-be_write16(&rec->dbfld[rec_cnt].fldlen, length);
-strcpy(tbufp, (const char*)data);
-tbufp += (length + 1) & (~1);
-break;
-case RECTYPE_DATE:
-length = 4;
-be_write16(&rec->dbfld[rec_cnt].fldlen, length);
-be_write32(tbufp, ((time_t)data - EPOCH_1904)/ (3600 * 24));
-tbufp += length;
-break;
-default:
-abort();
-}
-rec_cnt++;
-
-return length;
-}
-
-static void
-gcdb_write_wpt(const waypoint* wpt)
-{
-struct dbrec* rec;
-int reclen;
-char tbuf[100];
-
-/*
-* We don't really know how many fields we'll have or how long
-* they'll be so we'll just lazily create a huge place to hold them.
-*/
-rec = (struct dbrec*) xcalloc(sizeof(*rec) + 500, 1);
-
-gcdb_add_to_rec(rec, "gcna", RECTYPE_TEXT, wpt->description);
-gcdb_add_to_rec(rec, "gcid", RECTYPE_TEXT, wpt->shortname);
-
-gcdb_add_to_rec(rec, "lat0", RECTYPE_TEXT,
-wpt->latitude < 0 ? "S" : "N");
-
-sprintf(tbuf, "%d", (int) wpt->latitude);
-gcdb_add_to_rec(rec, "lat1", RECTYPE_TEXT, tbuf);
-
-sprintf(tbuf, "%f", 60 * (wpt->latitude -
-(int) wpt->latitude));
-gcdb_add_to_rec(rec, "lat2", RECTYPE_TEXT, tbuf);
-
-
-gcdb_add_to_rec(rec, "lon0", RECTYPE_TEXT,
-wpt->longitude < 0 ? "W" : "E");
-
-sprintf(tbuf, "%d", (int) wpt->longitude);
-gcdb_add_to_rec(rec, "lon1", RECTYPE_TEXT, tbuf);
-
-sprintf(tbuf, "%f", 60 * (wpt->longitude -
-(int) wpt->longitude));
-gcdb_add_to_rec(rec, "lon2", RECTYPE_TEXT, tbuf);
-
-if (wpt->gc_data->diff) {
-sprintf(tbuf, "%f", wpt->gc_data->diff / 10.0);
-gcdb_add_to_rec(rec, "diff", RECTYPE_TEXT, tbuf);
-}
-
-if (wpt->gc_data->terr) {
-sprintf(tbuf, "%f", wpt->gc_data->terr / 10.0);
-gcdb_add_to_rec(rec, "terr", RECTYPE_TEXT, tbuf);
-}
-
-#if 0
-/* This really is the date of the find,
-* not the cache creation date.
-*/
-if (wpt->creation_time) {
-gcdb_add_to_rec(rec, "date", RECTYPE_DATE, (void*) wpt->GetCreationTime());
-}
-#endif
-
-/*
-* We're done. Build the record.
-*/
-reclen = gcdb_add_to_rec(rec, NULL, (gcdb_rectype)0, NULL);
-
-pdb_write_rec(file_out, 0, 2, ct++, rec, reclen);
-xfree(rec);
-}
-
-static void
-data_write(void)
-{
- strncpy(file_out->name, out_fname, PDB_DBNAMELEN);
- strncpy(file_out->name, "GeocachingDB", PDB_DBNAMELEN);
- file_out->name[PDB_DBNAMELEN-1] = 0;
- file_out->attr = PDB_FLAG_BACKUP;
- file_out->ctime = file_out->mtime = current_time().toTime_t() + 2082844800U;
- file_out->type = MYTYPE; /* CWpt */
- file_out->creator = MYCREATOR; /* cGPS */
- file_out->version = 1;
-
- waypt_disp_all(gcdb_write_wpt);
-}
-
-
-ff_vecs_t gcdb_vecs = {
- ff_type_file,
- FF_CAP_RW_WPT,
- rd_init,
- wr_init,
- rd_deinit,
- wr_deinit,
- data_read,
- data_write,
- NULL,
- NULL,
- CET_CHARSET_ASCII, 0 /* CET-REVIEW */
-};
-#endif
+++ /dev/null
-/*
- Read and write GeoNiche files.
-
- Copyright (C) 2003 Rick Richardson <rickr@mn.rr.com>
- Copyright (C) 2006 Robert Lipe <robertlipe@usa.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
-
- */
-
-#include "defs.h"
-#if PDBFMTS_ENABLED
-#include "pdbfile.h"
-#include "jeeps/gpsmath.h"
-#include "garmin_tables.h"
-
-#include <math.h>
-#include <stdlib.h>
-
-#define MYNAME "Geoniche"
-#define MYTYPE_ASC 0x50454e44 /* PEND */
-#define MYTYPE_BIN 0x44415441 /* DATA */
-#define MYCREATOR 0x47656f4e /* GeoN */
-
-#undef GEONICHE_DBG
-
-static pdbfile* file_in, *file_out;
-static const char* FilenameOut;
-static int rec_ct;
-static int ct;
-static char Rec0Magic[] = "68000NV4Q2";
-
-static char* Arg_dbname = NULL;
-static char* Arg_category = NULL;
-
-static
-arglist_t Args[] = {
- {
- "dbname", &Arg_dbname,
- "Database name (filename)", NULL, ARGTYPE_STRING, ARG_NOMINMAX
- },
- {
- "category", &Arg_category,
- "Category name (Cache)", NULL, ARGTYPE_STRING, ARG_NOMINMAX
- },
- ARG_TERMINATOR
-};
-
-#define ARG_FREE(X) do { if (X) { xfree(X); X = NULL; } } while (0)
-
-/*
- * Conversions between gc.com ID's and GID's
- */
-static char GcSet[] = "0123456789ABCDEFGHJKMNPQRTVWXYZ";
-static int GcOffset = 16 * 31 * 31 * 31 - 65536;
-
-static int
-gid2id(char* gid)
-{
- char* p;
- int i, val;
-
- if (strncmp(gid, "GC", 2) != 0) {
- return -1;
- }
- if (strlen(gid) != 6) {
- return -1;
- }
- gid += 2;
-
- if (strcmp(gid, "G000") < 0) {
- return strtol(gid, NULL, 16);
- }
-
- for (val = i = 0; i < 4; ++i) {
- val *= 31;
- p = strchr(GcSet, gid[i]);
- if (!p) {
- return -1;
- }
- val += p - GcSet;
- }
- return val - GcOffset;
-}
-
-static void
-id2gid(char gid[6+1], int id)
-{
- gid[0] = 0;
- if (id < 0) {
- return;
- } else if (id < 65536) {
- snprintf(gid, 6+1, "GC%04X", id);
- } else {
- int i;
-
- id += GcOffset;
- gid[0] = 'G';
- gid[1] = 'C';
- for (i = 5; i >= 2; --i) {
- gid[i] = GcSet[id%31];
- id /= 31;
- }
- gid[6] = 0;
- if (id) {
- gid[0] = 0;
- }
- }
- return;
-}
-
-static void
-rd_init(const char* fname)
-{
- file_in = pdb_open(fname, MYNAME);
-}
-
-static void
-rd_deinit(void)
-{
- pdb_close(file_in);
- ARG_FREE(Arg_dbname);
- ARG_FREE(Arg_category);
-}
-
-static void
-wr_init(const char* fname)
-{
- file_out = pdb_create(fname, MYNAME);
- FilenameOut = fname;
-}
-
-static void
-wr_deinit(void)
-{
- pdb_close(file_out);
- ARG_FREE(Arg_dbname);
- ARG_FREE(Arg_category);
-}
-
-static char*
-field(char** pp, int* lenp)
-{
- int len = *lenp;
- char* p = *pp;
- char* dp, *dbuf;
- int state = 0;
-
- if (len == 0 || *p == 0) {
- return NULL;
- }
-
- dbuf = dp = (char*) xmalloc(len);
- while (len) {
- char ch;
-
- ch = *p++;
- --len;
- if (ch == 0 || len == 0) {
- break;
- }
- switch (state) {
- case 0:
- if (ch == '\\') {
- state = 1;
- } else if (ch == ',') {
- goto eof;
- } else {
- *dp++ = ch;
- }
- break;
- default:
- *dp++ = ch;
- state = 0;
- break;
- }
- }
-eof:
- *dp++ = 0;
- dbuf = (char*) xrealloc(dbuf, dp - dbuf);
- /* fprintf(stderr, "<%.8s> dbuf=%x, len=%d\n", *pp, dbuf, len); */
- *pp = p;
- *lenp = len;
- return dbuf;
-}
-
-static void
-geoniche_read_asc(void)
-{
- pdbrec_t* pdb_rec;
-
- /* Process record 0 */
- pdb_rec = file_in->rec_list;
- if (!pdb_rec || strcmp((char*) pdb_rec->data, Rec0Magic)) {
- fatal(MYNAME ": Bad record 0, not a GeoNiche file.\n");
- }
- pdb_rec = pdb_rec->next;
-
- /* Process the rest of the records */
- for (; pdb_rec; pdb_rec = pdb_rec->next) {
- waypoint* wpt;
- char* vdata;
- int vlen;
- char* p;
-
- int id;
- int route_id;
- char* title;
- QString category;
- double lat, lon, alt;
- char* datestr, *timestr;
- int icon;
- char* notes;
- char gid[6+1];
- struct tm tm;
-
- memset(&tm, 0, sizeof(tm));
-
- wpt = waypt_new();
- if (!wpt) {
- fatal(MYNAME ": Couldn't allocate waypoint.\n");
- }
- vdata = (char*) pdb_rec->data;
- vlen = pdb_rec->size;
-
- /* Field 1: Target */
- p = field(&vdata, &vlen);
- if (!p) {
- fatal(MYNAME ": Premature EOD processing field 1 (target).\n");
- }
- if (strcmp(p, "Route") == 0) {
- fatal(MYNAME ": Route record type is not implemented.\n");
- }
- if (strcmp(p, "Target")) {
- fatal(MYNAME ": Unknown record type '%s'.\n", p);
- }
- xfree(p);
-
- /* Field 2: Import ID number */
- p = field(&vdata, &vlen);
- if (!p) {
- fatal(MYNAME ": Premature EOD processing field 2 (ID).\n");
- }
- id = atoi(p);
- xfree(p);
-
- /* Field 3: Title */
- p = field(&vdata, &vlen);
- if (!p) {
- fatal(MYNAME ": Premature EOD processing field 3 (Title).\n");
- }
- title = p;
-
- /* Field 4: Route ID number */
- p = field(&vdata, &vlen);
- if (!p) {
- fatal(MYNAME ": Premature EOD processing field 4 (Route ID).\n");
- }
- route_id = atoi(p);
- xfree(p);
-
- /* Field 5: Category */
- p = field(&vdata, &vlen);
- if (!p) {
- fatal(MYNAME ": Premature EOD processing field 5 (Category).\n");
- }
- category = p;
- xfree(p);
-
- /* Field 6: Latitude */
- p = field(&vdata, &vlen);
- if (!p) {
- fatal(MYNAME ": Premature EOD processing field 6 (Latitude).\n");
- }
- lat = atof(p);
- xfree(p);
-
- /* Field 7: Longitude */
- p = field(&vdata, &vlen);
- if (!p) {
- fatal(MYNAME ": Premature EOD processing field 7 (Longitude).\n");
- }
- lon = atof(p);
- xfree(p);
-
- /* Field 8: Altitude */
- p = field(&vdata, &vlen);
- if (!p) {
- fatal(MYNAME ": Premature EOD processing field 8 (Altitude).\n");
- }
- alt = atof(p);
- xfree(p);
-
- /* Field 9: Creation date */
- p = field(&vdata, &vlen);
- if (!p) {
- fatal(MYNAME ": Premature EOD processing field 9 (Creation date).\n");
- }
- datestr = p;
-
- /* Field 10: Creation time */
- p = field(&vdata, &vlen);
- if (!p) {
- fatal(MYNAME ": Premature EOD processing field 10 (Creation time).\n");
- }
- timestr = p;
-
- /* Field 11: Visited date */
- p = field(&vdata, &vlen);
- if (!p) {
- fatal(MYNAME ": Premature EOD processing field 11 (Visited date).\n");
- }
- xfree(p);
-
- /* Field 12: Visited time */
- p = field(&vdata, &vlen);
- if (!p) {
- fatal(MYNAME ": Premature EOD processing field 12 (Visited time).\n");
- }
- xfree(p);
-
- /* Field 13: Icon color (R G B) */
- p = field(&vdata, &vlen);
- if (!p) {
- fatal(MYNAME ": Premature EOD processing field 13 (Icon color).\n");
- }
- xfree(p);
-
- /* Field 14: icon number */
- p = field(&vdata, &vlen);
- if (!p) {
- fatal(MYNAME ": Premature EOD processing field 14 (Icon number).\n");
- }
- icon = atoi(p);
- xfree(p);
-
- /* Field 15: unused */
- p = field(&vdata, &vlen);
- if (!p) {
- fatal(MYNAME ": Premature EOD processing field 15 (unused1).\n");
- }
- xfree(p);
-
- /* Field 16: unused */
- p = field(&vdata, &vlen);
- if (!p) {
- fatal(MYNAME ": Premature EOD processing field 16 (unused2).\n");
- }
- xfree(p);
-
- /* Field 17: unused */
- p = field(&vdata, &vlen);
- if (!p) {
- fatal(MYNAME ": Premature EOD processing field 17 (unused3).\n");
- }
- xfree(p);
-
- /* Field 18: Notes */
- p = field(&vdata, &vlen);
- if (!p) {
- fatal(MYNAME ": Premature EOD processing field 18 (Notes).\n");
- }
- notes = p;
-
- sscanf(datestr, "%d/%d/%d", &tm.tm_mon, &tm.tm_mday, &tm.tm_year);
- tm.tm_mon -= 1;
- tm.tm_year -= 1900;
- sscanf(timestr, "%d:%d:%d", &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
- if (tm.tm_year >= 1970) {
- wpt->SetCreationTime(mktime(&tm));
- }
- xfree(datestr);
- xfree(timestr);
-
- id2gid(gid, id);
- wpt->latitude = lat;
- wpt->longitude = lon;
- wpt->altitude = alt;
- wpt->icon_descr = category;
-
- if (gid[0]) {
- wpt->shortname = xstrdup(gid);
- wpt->description = title;
- wpt->notes = notes;
- } else {
- wpt->shortname = xstrdup(title);
- wpt->description = title;
- wpt->notes = notes;
- }
-
- waypt_add(wpt);
- }
-}
-
-static const char* geoniche_icon_map[] = /* MPS */
-{
- /* 21 */ "Cross",
- /* 22 */ "Cross (light)",
- /* 23 */ "Cross (little)",
- /* 24 */ "Cross (straight)",
- /* 25 */ "Cross (light straight)",
- /* 26 */ "Cross (little straight)",
- /* 27 */ NULL,
- /* 28 */ NULL,
- /* 29 */ NULL,
- /* 2A */ "Flag",
- /* 2B */ "Car", /* 56 */
- /* 2C */ "Gas Station", /* 8 */
- /* 2D */ "Observation Point",
- /* 2E */ "Scenic Area", /* 48 */
- /* 2F */ "City",
- /* 30 */ "Mountains",
- /* 31 */ "Park", /* 46 */
- /* 32 */ "Forest", /* 105 */
- /* 33 */ "Campground", /* 38 */
- /* 34 */ NULL,
- /* 35 */ "Men",
- /* 36 */ "Woman",
- /* 37 */ "Hotel", /* 59 */
- /* 38 */ "Residence", /* 10 */
- /* 39 */ "Restaurant", /* 11 */
- /* 3A */ "Cafe",
- /* 3B */ NULL,
- /* 3C */ "Airport", /* 107 */
- /* 3D */ "Medical Facility", /* 43 */
- /* 3E */ "Ropeway",
- /* 3F */ "Sailing Area",
- /* 40 */ "Anchor",
- /* 41 */ NULL, /* Half Anchor ??? */
- /* 42 */ "Fishing Area", /* 7 */
- /* 43 */ "Stop Sign",
- /* 44 */ "Question Sign",
- /* 45 */ NULL,
- /* 46 */ NULL,
- /* 47 */ "Euro Sign",
- /* 48 */ "Bank", /* 6 */
- /* 49 */ NULL,
- /* 4A */ "Left Arrow",
- /* 4B */ "Right Arrow",
- /* 4C */ "Traditional Cache",
- /* 4D */ "Multi-Cache", /* 86 */
- /* 4E */ "Virtual Cache", /* 48 */
- /* 4F */ "Letterbox Cache",
- /* 50 */ "Event Cache", /* 47 */
- /* 51 */ "Webcam Cache", /* 90 */
- /* 52 */ "Mystery or puzzle Cache",
-};
-
-static const QString
-geoniche_icon_to_descr(const int no)
-{
- const char* result = NULL;
-
- if (no >= 0x21) {
- int i = no - 0x21;
- if (i <= 49) {
- result = geoniche_icon_map[i];
- }
- }
- return result;
-}
-
-static void
-geoniche_read_bin(void)
-{
- pdbrec_t* pdb_rec;
-
- /* Process records */
-
- for (pdb_rec = file_in->rec_list; pdb_rec != NULL; pdb_rec = pdb_rec->next) {
- char* vdata = (char*) pdb_rec->data;
- struct tm created, visited;
- int icon_nr, selected;
- int latdeg, londeg;
- double lat, lon, altitude;
- waypoint* waypt;
-
- memset(&visited, 0, sizeof(visited));
- memset(&created, 0, sizeof(created));
-
- latdeg = be_read16(vdata + 0);
- lat = be_read32(vdata + 2);
- londeg = be_read16(vdata + 6);
- lon = be_read32(vdata + 8);
- altitude = (float) be_read32(vdata + 12);
- selected = vdata[16];
- created.tm_min = be_read16(vdata + 20);
- created.tm_hour = be_read16(vdata + 22);
- created.tm_mday = be_read16(vdata + 24);
- created.tm_mon = be_read16(vdata + 26);
- created.tm_year = be_read16(vdata + 28);
- visited.tm_min = be_read16(vdata + 34);
- visited.tm_hour = be_read16(vdata + 36);
- visited.tm_mday = be_read16(vdata + 38);
- visited.tm_mon = be_read16(vdata + 40);
- visited.tm_year = be_read16(vdata + 42);
-
-#ifdef GEONICHE_DBG
- printf(MYNAME "-date: %04d/%02d/%02d, %02d:%02d (%04d/%02d/%02d, %02d:%02d)\n",
- created.tm_year, created.tm_mon, created.tm_mday, created.tm_hour, created.tm_min,
- visited.tm_year, visited.tm_mon, visited.tm_mday, visited.tm_hour, visited.tm_min);
-#endif
- icon_nr = vdata[62];
-
- latdeg = 89 - latdeg;
- lat = lat * (double) 0.0000006;
- if (latdeg >= 0) {
- lat = (double) 60.0 - lat;
- } else {
- latdeg++;
- }
-
- lon = lon * (double) 0.0000006;
- while (londeg >= 360) {
- londeg-=360;
- }
- if (londeg > 180) {
- lon = (double) 60.0 - lon;
- londeg = londeg - 359;
- }
-
- created.tm_year-=1900;
- created.tm_mon--;
-
- waypt = waypt_new();
-
- waypt->shortname = xstrdup(vdata + 63);
- waypt->altitude = altitude;
- waypt->SetCreationTime(mkgmtime(&created));
-
- GPS_Math_DegMin_To_Deg(latdeg, lat, &waypt->latitude);
- GPS_Math_DegMin_To_Deg(londeg, lon, &waypt->longitude);
-
- waypt->icon_descr = geoniche_icon_to_descr(icon_nr);
- waypt_add(waypt);
- }
-}
-
-static void
-data_read(void)
-{
- if (file_in->creator != MYCREATOR) {
- fatal(MYNAME ": Not a GeoNiche file.\n");
- }
-
- switch (file_in->type) {
- case MYTYPE_ASC:
- geoniche_read_asc();
- break;
- case MYTYPE_BIN:
- geoniche_read_bin();
- break;
- default:
- fatal(MYNAME ": Unsupported GeoNiche file.\n");
- }
-}
-
-static char*
-enscape(char* s)
-{
- char* buf, *d;
-
- if (!s) {
- d = (char*) xmalloc(1);
- *d = 0;
- return d;
- }
- buf = d = (char*) xmalloc(strlen(s) * 2 + 1);
- for (; *s; ++s) {
-
- /*
- * 3 May 06: need to escape single quotes for v1.40 release
- */
-
- if (*s == '\\' || *s == ',' || *s == '\'') {
- *d++ = '\\';
- *d++ = *s;
- }
-
- /* 3 May 06: stop stripping for better readability
- *
- * else if ((*s == '\r') || (*s == '\n'))
- * *d++ = ' ';
- */
- else {
- *d++ = *s;
- }
- }
-
- *d = 0;
- return buf;
-}
-
-/*
- * Attempt to map an icon description into a GeoNiche icon number
- */
-static int
-wpt2icon(const waypoint* wpt)
-{
- QString desc = wpt->icon_descr;
-
- if (desc.isNull()) {
- return 0;
- } else if (desc.contains("reg")) {
- return 43;
- } else if (desc.contains("trad")) {
- return 43;
- } else if (desc.contains("multi")) {
- return 44;
- } else if (desc.contains("offset")) {
- return 44;
- } else if (desc.contains("virt")) {
- return 45;
- } else if (desc.contains("loca")) {
- return 45;
- } else if (desc.contains("event")) {
- return 46;
- } else if (desc.contains("lett")) {
- return 47;
- } else if (desc.contains("hyb")) {
- return 47;
- } else if (desc.contains("unk")) {
- return 48;
- } else if (desc.contains("cam")) {
- return 49;
- }
-
- switch (wpt->gc_data->type) {
- case gt_traditional:
- return 43;
- case gt_multi:
- return 44;
- case gt_locationless:
- return 45;
- case gt_earth:
- return 45;
- case gt_virtual:
- return 45;
- case gt_letterbox:
- return 46;
- case gt_event:
- return 47;
- case gt_cito:
- return 47;
- case gt_suprise:
- return 48;
- case gt_webcam:
- return 49;
- case gt_unknown:
- return 0;
- case gt_benchmark:
- return 0;
- case gt_ape:
- return 0;
- case gt_mega:
- return 0;
- case gt_wherigo:
- return 0;
- }
-
- return 0;
-}
-
-static char*
-geoniche_geostuff(const waypoint* wpt)
-{
- char* gs = NULL, *tmp1, *tmp2, *tmp3;
- char tbuf[10240];
-
- if (!wpt->gc_data->terr) {
- return NULL;
- }
-
- snprintf(tbuf, sizeof(tbuf), "\n%s by %s\n\n", gs_get_cachetype(wpt->gc_data->type), wpt->gc_data->placer.toUtf8().data());
- gs = xstrappend(gs, tbuf);
-
- /*
- * 3 May 06: Removed duplicated information
- *
- * snprintf(tbuf, sizeof(tbuf), "Waypoint: %s %s\n", wpt->shortname, wpt->description);
- * gs = xstrappend(gs, tbuf);
- */
-
- /*
- * 3 May 06: Added container type
- */
- snprintf(tbuf, sizeof(tbuf), "Container: %s\nDifficulty: %3.1f\nTerrain: %3.1f\n\n", gs_get_container(wpt->gc_data->container), wpt->gc_data->diff/10.0, wpt->gc_data->terr/10.0);
- gs = xstrappend(gs, tbuf);
-
- tmp1 = strip_html(&wpt->gc_data->desc_short);
- tmp2 = strip_html(&wpt->gc_data->desc_long);
- gs = xstrappend(gs, tmp1);
- gs = xstrappend(gs, tmp2);
-
- tmp3 = rot13(wpt->gc_data->hint);
- snprintf(tbuf, sizeof(tbuf), "\n\nHint: %s\n", tmp3);
- gs = xstrappend(gs, tbuf);
-
- xfree(tmp1);
- xfree(tmp2);
- xfree(tmp3);
-
- tmp1 = enscape(gs);
- xfree(gs);
-
- return tmp1;
-}
-
-static void
-geoniche_writewpt(const waypoint* wpt)
-{
- int vlen;
- char* vdata;
- char* title;
- struct tm tm;
- char datestr[10+1];
- char timestr[8+1];
- char* notes;
- int id;
- time_t tx;
- char* gs;
-
- if (rec_ct == 0) {
- pdb_write_rec(file_out, 0, 0, ct++, Rec0Magic, sizeof(Rec0Magic));
- }
-
- if (wpt->description && wpt->description[0]) {
- title = enscape(wpt->description);
- } else {
- title = enscape(wpt->shortname);
- }
-
- id = gid2id(wpt->shortname);
- if (id < 0) {
- id = rec_ct;
- }
-
- if (wpt->GetCreationTime().isValid()) {
- tx = wpt->GetCreationTime().toTime_t();
- } else {
- tx = gpsbabel_time;
- }
- if (tx == 0) { /* maybe zero during testo (freezed time) */
- strcpy(datestr, "01/01/1904"); /* this seems to be the uninitialized date value for geoniche */
- strcpy(timestr, "00:00:00");
- } else {
- tm = *localtime(&tx);
- strftime(datestr, sizeof(datestr), "%m/%d/%Y", &tm);
- strftime(timestr, sizeof(timestr), "%H:%M:%S", &tm);
- }
-
- /* Notes field MUST have soemthing in it */
- if (!wpt->notes || wpt->notes[0] == 0) {
- notes = xstrdup(title);
- } else {
- notes = enscape(wpt->notes);
- }
-
- gs = geoniche_geostuff(wpt);
- if (gs) {
- notes = xstrappend(notes, gs);
- xfree(gs);
- }
- /* last chance to fill notes with something */
- if (*notes == '\0') {
- notes = xstrappend(notes, "(notes)");
- }
-
- vlen = xasprintf(&vdata,
- "Target,%d,%s,,%s,%f,%f,%f,%s,%s,,,,%d,,,,%s"
- , id
- , title
- /* route ID */
- , Arg_category ? Arg_category : "Cache"
- , wpt->latitude
- , wpt->longitude
- , wpt->altitude
- , datestr
- , timestr
- /* visited date */
- /* visited time */
- /* icon color R G B */
- , wpt2icon(wpt)
- /* unused1 */
- /* unused2 */
- /* unused3 */
- , notes
- );
-
- pdb_write_rec(file_out, 0, 0, ct++, vdata, vlen + 1);
-
- xfree(notes);
- xfree(title);
- xfree(vdata);
-
- rec_ct++;
-}
-
-static void
-data_write(void)
-{
- if (Arg_dbname) {
- if (case_ignore_strcmp(Arg_dbname, "GeoNiche Targets") == 0) {
- fatal(MYNAME ": Reserved database name!\n");
- }
- strncpy(file_out->name, Arg_dbname, PDB_DBNAMELEN);
- } else {
- strncpy(file_out->name, FilenameOut, PDB_DBNAMELEN);
- }
- file_out->name[PDB_DBNAMELEN-1] = 0;
-
- file_out->attr = PDB_FLAG_BACKUP;
- file_out->ctime = file_out->mtime = current_time().toTime_t() + (49*365 + 17*366) * (60*60*24);
- file_out->type = MYTYPE_ASC;
- file_out->creator = MYCREATOR;
- file_out->version = 0;
- file_out->revision = 1;
-
- rec_ct = 0;
- ct = 0;
- waypt_disp_all(geoniche_writewpt);
-}
-
-
-ff_vecs_t geoniche_vecs = {
- ff_type_file,
- FF_CAP_RW_WPT,
- rd_init,
- wr_init,
- rd_deinit,
- wr_deinit,
- data_read,
- data_write,
- NULL,
- Args,
- CET_CHARSET_MS_ANSI, 0 /* CET-REVIEW */
-};
-#endif
+++ /dev/null
-/*
- Read and write GPilotS files.
-
- Copyright (C) 2003 Robert Lipe, robertlipe@usa.net
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
-
- */
-
-#include "defs.h"
-#if PDBFMTS_ENABLED
-#include "pdbfile.h"
-#include "garmin_tables.h"
-
-#define MYNAME "GPilotS"
-#define MYWPT 0x57707473 /* Wpts */
-#define MYTRK 0x54726b73 /* Trks */
-#define MYRTE 0x57707473 /* Wpts */
-#define MYCREATOR 0x4750696c /* GPil */
-
-
-/*
- * Structures grafted from http://www.cru.fr/perso/cc/GPilotS/
- */
-
-
-typedef struct {
- long lat; /* latitude in semicircles */
- long lon; /* longitude in semicircles */
-}
-Semicircle_Type;
-
-typedef struct {
- char ident[6]; /* identifier */
- unsigned char lat[4]; /* position */
- unsigned char lon[4]; /* position */
- unsigned char unused[4]; /* should be set to zero */
- char cmnt[40]; /* comment */
- unsigned char smbl; /* symbol id */
- unsigned char dspl; /* display option */
-} D103_Wpt_Type;
-
-typedef union {
- float f;
- unsigned int i;
-} fi_t;
-
-typedef struct { /* size */
- unsigned char wpt_class; /* class (see below) 1 */
- unsigned char color; /* color (see below) 1 */
- unsigned char dspl; /* display options (see below) 1 */
- unsigned char attr; /* attributes (see below) 1 */
- unsigned char smbl[2]; /* waypoint symbol 2 */
- unsigned char subclass[18]; /* subclass 18 */
- unsigned char lat[4]; /* position */
- unsigned char lon[4]; /* position */
- float alt; /* altitude in meters 4 */
- float dpth; /* depth in meters 4 */
- float dist; /* proximity distance in meters 4 */
- char state[2]; /* state 2 */
- char cc[2]; /* country code 2 */
- char varlenstrs[1]; /* start of variable length strings */
- /* G_char ident[]; variable length string 1-51 */
- /* G_char comment[]; waypoint user comment 1-51 */
- /* G_char facility[]; facility name 1-31 */
- /* G_char city[]; city name 1-25 */
- /* G_char addr[]; address number 1-51 */
- /* G_char cross_road[]; intersecting road label 1-51 */
-}
-D108_Wpt_Type;
-
-typedef struct { /* structure de waypoint "interne" */
- unsigned char ident[51]; /* identifier (50 + '0') */
- Semicircle_Type posn; /* position (common to all Garmin types) */
- unsigned char cmnt[51]; /* comment (50 + '0') */
- float dst; /* proximity distance */
- float alt; /* altitude */
- int smbl; /* symbol id */
- unsigned char dspl; /* display option */
- unsigned char color; /* color */
-}
-Custom_Wpt_Type;
-
-typedef struct { /* internal track header */
- char name[256]; /* nom du groupe de trackpoints */
- unsigned char dspl; /* display on the map ? */
- unsigned char color; /* color */
- unsigned char type; /* type of following track points */
- unsigned char unused; /* type of following track points */
- unsigned char number[2]; /* number of track points */
- unsigned char latmin[4]; /* latitude min */
- unsigned char latmax[4]; /* latitude max */
- unsigned char lonmin[4]; /* longitude min */
- unsigned char lonmax[4]; /* longitude max */
- unsigned char unused2[2]; /* type of following track points */
-}
-Custom_Trk_Hdr_Type;
-
-typedef struct {
- unsigned char lat[4]; /* position */
- unsigned char lon[4]; /* position */
- unsigned char time[4];
- unsigned char alt[4];
- unsigned char new_trk;
- unsigned char unused;
-} Custom_Trk_Point_Type;
-
-typedef struct { /* custom compact track point type */
- unsigned char lat[4]; /* position */
- unsigned char lon[4]; /* position */
- unsigned char new_trk;
- unsigned char unused;
-} Compact_Trk_Point_Type; /* size : 10 bytes */
-
-struct record {
- struct {
- unsigned char type;
- unsigned short size;
- unsigned int version;
- } header;
- union {
- D103_Wpt_Type d103;
- D108_Wpt_Type d108;
- Custom_Wpt_Type CustWpt;
- Custom_Trk_Hdr_Type CustTrkHdr;
-#if LATER
- Custom_Rte_Hdr_Type CustRteHdr;
-#endif
- } wpt;
-};
-
-
-static pdbfile* file_in, *file_out;
-static const char* out_fname;
-static int ct = 0;
-static char* dbname = NULL;
-
-static
-arglist_t my_args[] = {
- {"dbname", &dbname, "Database name", NULL, ARGTYPE_STRING, ARG_NOMINMAX},
- ARG_TERMINATOR
-};
-
-static void
-rd_init(const char* fname)
-{
- file_in = pdb_open(fname, MYNAME);
-}
-
-static void
-rd_deinit(void)
-{
- pdb_close(file_in);
- if (dbname) {
- xfree(dbname);
- dbname = NULL;
- }
-}
-
-static void
-wr_init(const char* fname)
-{
- file_out = pdb_create(fname, MYNAME);
- out_fname = fname;
-}
-
-static void
-wr_deinit(void)
-{
- pdb_close(file_out);
- if (dbname) {
- xfree(dbname);
- dbname = NULL;
- }
-}
-
-static void
-data_read(void)
-{
- struct record* rec;
- pdbrec_t* pdb_rec;
- route_head* track_head = NULL;
-
- if (file_in->creator != MYCREATOR) {
- fatal(MYNAME ": Not a %s file.\n", MYNAME);
- }
-
- switch (file_in->type) {
- case MYWPT:
- /* blah */
- break;
- case MYTRK:
- /* blah */
- break;
- default:
- fatal(MYNAME ": Unknown file type 0x%x\n", (int) file_in->type);
- }
-
- for (pdb_rec = file_in->rec_list; pdb_rec; pdb_rec=pdb_rec->next) {
- waypoint* wpt_tmp;
- Custom_Trk_Point_Type* tp_cust;
- Compact_Trk_Point_Type* tp_comp;
- int lat;
- int lon;
- int sz;
- fi_t fi;
- int trk_num = 0;
- int trk_seg_num = 1;
- char trk_seg_num_buf[10];
- const char* trk_name = "";
-
- wpt_tmp = waypt_new();
-
- rec = (struct record*) pdb_rec->data;
- switch (rec->header.type) {
- /*
- * G103Type
- */
- case 4:
- wpt_tmp->shortname = xstrndupt(rec->wpt.d103.ident, sizeof(rec->wpt.d103.ident));
- wpt_tmp->description = xstrndupt(rec->wpt.d103.cmnt, sizeof(rec->wpt.d103.cmnt));
- /* This is odd. This is a Palm DB file,
- * yet the data appears to be little endian,
- * not appropriate the the actual Palm.
- */
- lon = le_read32(&rec->wpt.d103.lon);
- lat = le_read32(&rec->wpt.d103.lat);
- wpt_tmp->longitude = lon / 2147483648.0 * 180.0;
- wpt_tmp->latitude = lat / 2147483648.0 * 180.0;
- waypt_add(wpt_tmp);
- break;
- /*
- * G108Type
- */
- case 9:
- wpt_tmp->shortname = xstrndupt(rec->wpt.d108.varlenstrs, 50);
- wpt_tmp->description = xstrndupt(rec->wpt.d108.varlenstrs + strlen(wpt_tmp->shortname) + 1, 50);
- /* This is odd. This is a Palm DB file,
- * yet the data appears to be little endian,
- * not appropriate the the actual Palm.
- */
- lon = le_read32(&rec->wpt.d108.lon);
- lat = le_read32(&rec->wpt.d108.lat);
- wpt_tmp->longitude = lon / 2147483648.0 * 180.0;
- wpt_tmp->latitude = lat / 2147483648.0 * 180.0;
- fi.i = le_read32(&rec->wpt.d108.alt);
- wpt_tmp->altitude = fi.f;
- fi.i = le_read32(&rec->wpt.d108.dpth);
- WAYPT_SET(wpt_tmp, depth, fi.f);
- fi.i = le_read32(&rec->wpt.d108.dist);
- WAYPT_SET(wpt_tmp, proximity, fi.f);
- wpt_tmp->icon_descr = gt_find_desc_from_icon_number((rec->wpt.d108.smbl[1] << 8) + rec->wpt.d108.smbl[0], PCX, NULL);
- waypt_add(wpt_tmp);
- break;
-
- /*
- * CustomTrkHdr
- */
- case 101:
- trk_name = rec->wpt.CustTrkHdr.name;
- sz = be_read16(&rec->wpt.CustTrkHdr.number);
-
- /* switch between custom track points and compact track points.
- * (compact points have no altitude and time info.
- */
- switch (rec->wpt.CustTrkHdr.type) {
- case 102:
- tp_cust = (Custom_Trk_Point_Type*)((char*) pdb_rec->data + sizeof(rec->header) + sizeof(rec->wpt.CustTrkHdr));
- while (sz--) {
- if ((int)(tp_cust->new_trk) == 1 || trk_seg_num == 1) {
- /*
- * Start a new track segment
- */
- track_head = route_head_alloc();
- if (trk_seg_num == 1) {
- track_head->rte_name = xstrdup(trk_name);
- } else {
- /* name in the form TRACKNAME #n */
- snprintf(trk_seg_num_buf, sizeof(trk_seg_num_buf), "%d", trk_seg_num);
- track_head->rte_name = (char*) xmalloc(strlen(trk_name)+strlen(trk_seg_num_buf)+3);
- sprintf(track_head->rte_name, "%s #%s", trk_name, trk_seg_num_buf);
- }
- trk_seg_num++;
- track_head->rte_num = trk_num;
- trk_num++;
- track_add_head(track_head);
- }
-
- wpt_tmp = waypt_new();
-
- /* This is even more odd.
- * Track data is stored as big endian while
- * waypoint data is little endian!?
- */
- lon = be_read32(&tp_cust->lon);
- lat = be_read32(&tp_cust->lat);
- wpt_tmp->longitude = lon / 2147483648.0 * 180.0;
- wpt_tmp->latitude = lat / 2147483648.0 * 180.0;
- /*
- * Convert Garmin/GPilotS time format to gpsbabel time format.
- * Garmin/GPilotS count seconds from "UTC 12:00 AM December 31 1989".
- * gpsbabel counts seconds from "UTC 12:00 AM January 1 1970".
- */
- wpt_tmp->SetCreationTime(be_read32(&tp_cust->time) + 631065600);
- fi.i = be_read32(&tp_cust->alt);
- wpt_tmp->altitude = fi.f;
- track_add_wpt(track_head, wpt_tmp);
- tp_cust++;
- }
- break;
- case 104:
- tp_comp = (Compact_Trk_Point_Type*)((char*) pdb_rec->data + sizeof(rec->header) + sizeof(rec->wpt.CustTrkHdr));
- while (sz--) {
- if ((int)(tp_comp->new_trk) == 1 || trk_seg_num == 1) {
- /*
- * Start a new track segment
- */
- track_head = route_head_alloc();
- if (trk_seg_num == 1) {
- track_head->rte_name = xstrdup(trk_name);
- } else {
- /* name in the form TRACKNAME #n */
- snprintf(trk_seg_num_buf, sizeof(trk_seg_num_buf), "%d", trk_seg_num);
- track_head->rte_name = (char*) xmalloc(strlen(trk_name)+strlen(trk_seg_num_buf)+3);
- sprintf(track_head->rte_name, "%s #%s", trk_name, trk_seg_num_buf);
- }
- trk_seg_num++;
- track_head->rte_num = trk_num;
- trk_num++;
- track_add_head(track_head);
- }
-
- wpt_tmp = waypt_new();
- lon = be_read32(&tp_comp->lon);
- lat = be_read32(&tp_comp->lat);
- wpt_tmp->longitude = lon / 2147483648.0 * 180.0;
- wpt_tmp->latitude = lat / 2147483648.0 * 180.0;
- track_add_wpt(track_head, wpt_tmp);
- tp_comp++;
- }
- break;
- default:
- fatal(MYNAME ": track point type %d not supported.\n", rec->wpt.CustTrkHdr.type);
- }
- break;
- default:
- fatal(MYNAME ": input record type %d not supported.\n", rec->header.type);
- }
-
- }
-}
-
-
-struct hdr {
- char* wpt_name;
- waypoint* wpt;
-};
-
-static void
-my_write_wpt(const waypoint* wpt)
-{
- struct record* rec;
- char* vdata;
- int lat, lon;
-
- rec = (struct record*) xcalloc(sizeof *rec, 1);
- vdata = (char*)rec + sizeof(*rec);
-
- rec->header.type = 4;
- rec->header.size = 5;
- rec->header.version = 6;
-
- strncpy(rec->wpt.d103.ident, wpt->shortname, sizeof(rec->wpt.d103.ident));
- strncpy(rec->wpt.d103.cmnt, wpt->description, sizeof(rec->wpt.d103.cmnt));
- lat = wpt->latitude / 180.0 * 2147483648.0;
- lon = wpt->longitude / 180.0 * 2147483648.0;
- le_write32(&rec->wpt.d103.lat, lat);
- le_write32(&rec->wpt.d103.lon, lon);
-
- pdb_write_rec(file_out, 0, ct, ct+1, rec, (char*)vdata - (char*)rec);
- ct++;
- xfree(rec);
-}
-
-static void
-data_write(void)
-{
- if (dbname) {
- strncpy(file_out->name, dbname, PDB_DBNAMELEN);
- } else {
- strncpy(file_out->name, out_fname, PDB_DBNAMELEN);
- }
-
- /*
- * Populate header.
- */
- file_out->name[PDB_DBNAMELEN-1] = 0;
- file_out->attr = PDB_FLAG_BACKUP;
- file_out->ctime = file_out->mtime = current_time().toTime_t() + 2082844800U;
-
- file_out->type = MYWPT;
- file_out->creator = MYCREATOR;
- file_out->version = 1;
-
- waypt_disp_all(my_write_wpt);
-}
-
-
-ff_vecs_t gpilots_vecs = {
- ff_type_file,
- { (ff_cap)(ff_cap_read | ff_cap_write), (ff_cap)(ff_cap_read | ff_cap_write), ff_cap_none},
- rd_init,
- wr_init,
- rd_deinit,
- wr_deinit,
- data_read,
- data_write,
- NULL,
- my_args,
- CET_CHARSET_ASCII, 0 /* CET-REVIEW */
-};
-#endif
+++ /dev/null
-/*
- Read and write GPSPilot Tracker files.
-
- Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
-
- */
-
-#include "defs.h"
-#if PDBFMTS_ENABLED
-#include "pdbfile.h"
-
-#define MYNAME "GPSPilot"
-#define MYTYPE_POINTS 0x706f696e /* poin */
-#define MYTYPE_AIRPORT 0x706f3030 /* po00 */
-#define MYTYPE_CITIES 0x706f3031 /* po01 */
-#define MYTYPE_LNDMRKS 0x706f3032 /* po02 */
-#define MYTYPE_NAVAIDS 0x706f3033 /* po03 */
-#define MYCREATOR 0x47704c69 /* GpLi */
-
-struct record {
- pdb_32 longitude; /* Big endian, long * 3.6e6 */
- pdb_32 latitude; /* similarly */
- pdb_16 elevation; /* meters */
- pdb_16 magvar; /* magnetic variation in degrees, neg = west */
-};
-
-struct runways {
- pdb_32 be_longitude; /* Big endian, long * 3.6e6 */
- pdb_32 be_latitude; /* similarly */
- pdb_32 en_longitude; /* Big endian, long * 3.6e6 */
- pdb_32 en_latitude; /* similarly */
-};
-
-static pdbfile* file_in, *file_out;
-static const char* out_fname;
-static char* dbname = NULL;
-static int ct;
-
-static
-arglist_t gpspilot_args[] = {
- {"dbname", &dbname, "Database name", NULL, ARGTYPE_STRING, ARG_NOMINMAX},
- ARG_TERMINATOR
-};
-
-static void
-rd_init(const char* fname)
-{
- file_in = pdb_open(fname, MYNAME);
-}
-
-static void
-rd_deinit(void)
-{
- pdb_close(file_in);
- if (dbname) {
- xfree(dbname);
- dbname = NULL;
- }
-}
-
-static void
-wr_init(const char* fname)
-{
- file_out = pdb_create(fname, MYNAME);
- out_fname = fname;
- ct = 0;
-}
-
-static void
-wr_deinit(void)
-{
- pdb_close(file_out);
- if (dbname) {
- xfree(dbname);
- dbname = NULL;
- }
-}
-
-static void
-data_read(void)
-{
- struct record* rec;
- pdbrec_t* pdb_rec;
-
- if ((file_in->creator != MYCREATOR)) {
- fatal(MYNAME ": Not a gpspilot file.\n");
- }
-
- switch (file_in->type) {
- case MYTYPE_AIRPORT:
- case MYTYPE_POINTS:
- case MYTYPE_CITIES:
- case MYTYPE_LNDMRKS:
- case MYTYPE_NAVAIDS:
- break;
- default:
- fatal(MYNAME ": Not a gpspilot file.\n");
- }
-
- for (pdb_rec = file_in->rec_list; pdb_rec; pdb_rec = pdb_rec->next) {
- waypoint* wpt_tmp;
- char* vdata;
-
- wpt_tmp = waypt_new();
-
- rec = (struct record*) pdb_rec->data;
- wpt_tmp->longitude = be_read32(&rec->longitude) / 3.6e6;
- wpt_tmp->latitude = be_read32(&rec->latitude) / 3.6e6;
- wpt_tmp->altitude =
- be_read16(&rec->elevation);
-
- vdata = (char*) pdb_rec->data + sizeof(*rec);
-
- /*
- * skip runway records if an airport.
- */
- if (pdb_rec->category == 0) {
- int numRunways;
- numRunways = be_read16(vdata);
- vdata += 2;
- vdata += (sizeof(struct runways) * numRunways);
- }
-
- /*
- * This maping is a bit contrived.
- * Name is up to 36. ID is up to 9.
- * Since 'ID' maps more clearly to "shortname" (and this
- * more likely to be resemble a wayoint name in another
- * receiver) we use that for shortname and use 'name' as
- * our description.
- */
- wpt_tmp->description = xstrdup(vdata);
- vdata = vdata + strlen(vdata) + 1;
-
- wpt_tmp->shortname = xstrdup(vdata);
- vdata = vdata + strlen(vdata) + 1;
-
- wpt_tmp->notes = xstrdup(vdata);
-
- waypt_add(wpt_tmp);
-
- }
-}
-
-
-static void
-gpspilot_writewpt(const waypoint* wpt)
-{
- struct record* rec;
- char* vdata;
-
- rec = (struct record*) xcalloc(sizeof(*rec)+206,1);
-
- be_write32(&rec->longitude, si_round(wpt->longitude * 3.6e6));
- be_write32(&rec->latitude, si_round(wpt->latitude * 3.6e6));
- be_write16(&rec->elevation, si_round(wpt->altitude));
- be_write16(&rec->magvar, 0);
-
- vdata = (char*)rec + sizeof(*rec);
- if (wpt->description) {
- strncpy(vdata, wpt->description, 36);
- vdata[35] = '\0';
- } else {
- vdata[0] ='\0';
- }
- vdata += strlen(vdata) + 1;
- if (wpt->shortname) {
- strncpy(vdata, wpt->shortname, 9);
- vdata[8] = '\0';
- } else {
- vdata[0] ='\0';
- }
- vdata += strlen(vdata) + 1;
-
- if (wpt->notes) {
- strncpy(vdata, wpt->notes, 161);
- vdata[160] = '\0';
- } else {
- vdata[0] ='\0';
- }
- vdata += strlen(vdata) + 1;
-
- pdb_write_rec(file_out, 0, 2, ct++, (void*)rec, (char*)vdata - (char*)rec);
-
- xfree(rec);
-}
-
-static void
-data_write(void)
-{
- if (dbname) {
- strncpy(file_out->name, dbname, PDB_DBNAMELEN);
- } else {
- strncpy(file_out->name, out_fname, PDB_DBNAMELEN);
- }
- file_out->name[PDB_DBNAMELEN-1] = 0;
- file_out->attr = PDB_FLAG_BACKUP;
- file_out->ctime = file_out->mtime = current_time().toTime_t() + 2082844800U;
- file_out->type = MYTYPE_POINTS;
- file_out->creator = MYCREATOR;
- file_out->version = 0;
-
- waypt_disp_all(gpspilot_writewpt);
-}
-
-
-ff_vecs_t gpspilot_vecs = {
- ff_type_file,
- FF_CAP_RW_WPT,
- rd_init,
- wr_init,
- rd_deinit,
- wr_deinit,
- data_read,
- data_write,
- NULL,
- gpspilot_args,
- CET_CHARSET_ASCII, 0 /* CET-REVIEW */
-};
-#endif
+++ /dev/null
-/*
-
- Support of Palm/OS files from Map&Guide based products like
- "PowerRoute" 5+6, "Motorrad Routenplaner"
-
- Copyright (C) 2005 Olaf Klein, o.b.klein@gpsbabel.org
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
-
-*/
-
-#include <ctype.h>
-#include <math.h>
-
-#include "defs.h"
-#if PDBFMTS_ENABLED
-#include "pdbfile.h"
-#include "jeeps/gpsmath.h"
-
-#define MYNAME "mag_pdb"
-
-#define PROUTE_MAGIC 0x766d6170 /* vmap */
-#define PROUTE_ROUTE 0x49444154 /* IDAT */
-
-static pdbfile* file_in;
-
-static arglist_t magpdb_args[] = {
- ARG_TERMINATOR
-};
-
-static double
-magpdb_to_degree(const int degx)
-{
- int m, d, x;
- double s, res;
-
- d = degx / 100000;
- x = degx % 100000;
- m = x / 1000;
- x = x % 1000;
- s = (double)(x) / 10;
-
- GPS_Math_DegMinSec_To_Deg(d, m, s, &res);
-
- return res;
-}
-
-static void
-magpdb_read_data(const char* data, const size_t data_len)
-{
- route_head* route;
- char* cin = (char*)data;
- char* cend = cin + data_len;
-
- route = route_head_alloc();
- route_add_head(route);
-
- while (cin < cend) {
- char* lend;
- int len;
-
- lend = strchr(cin, '\x0A');
- if (lend == NULL) {
- break;
- }
-
- len = (lend - cin);
- if (len > 0) {
- double distance;
- int hour, min;
- *lend = '\0';
-
- if (case_ignore_strncmp(cin, "Wegname=", 8) == 0) { /* This only works with the german release */
- /* test-data created with other releases are welcome */
- cin += 8;
- if (*cin != '\0') {
- route->rte_name = xstrdup(cin);
- }
- } else if (case_ignore_strncmp(cin, "Fahrzeit=", 9) == 0) {
- } else if (case_ignore_strncmp(cin, "Kosten=", 7) == 0) {
- } else if (case_ignore_strncmp(cin, "Entfernung=", 11) == 0) {
- }
- /* check, if line starts with time and distance */
- else if (3 == sscanf(cin, "%d:%d %lf", &hour, &min, &distance)) {
- char* buff, *comma;
-
- /* detect time-format settings, 12,0 or 12.0 */
-
- comma = strchr(cin, '.');
- buff = strchr(cin, ',');
- if (comma == NULL) {
- comma = buff;
- } else if ((buff != NULL) && (buff < comma)) {
- comma = buff;
- }
- if (comma != NULL) {
- char separator = *comma;
-
- /* now we are looking for a sequence like 0,1 NE (123456,654321) */
-
- buff = (char*) xmalloc(strlen(cin) + 1); /* safe target space for sscanf( ... */
-
- comma = cin;
- while ((comma = strchr(comma, separator))) {
- int i, xlat, xlon;
- waypoint* wpt;
- char* cx;
-
- comma++;
-
- if (isdigit(*comma) == 0) {
- continue;
- }
- if (isdigit(*(comma - 2)) == 0) {
- continue;
- }
-
- if (4 != sscanf(comma, "%d %s (%d,%d)", &i, buff, &xlon, &xlat)) {
- continue;
- }
- if (strchr("NESW", *buff) == NULL) {
- continue; /* north, east, ... */
- }
-
- cx = comma - 2; /* go left over delta distance */
- while (isdigit(*cx) != 0) {
- *cx-- = '\0';
- }
- cin = lrtrim(cin);
-
- for (i = 0; i < 2; i++) { /* skip time and distance at start of line */
- cin = strchr(cin, ' ');
- cin = lrtrim(cin);
- }
-
- wpt = waypt_new();
-
- wpt->latitude = magpdb_to_degree(xlat);
- wpt->longitude = magpdb_to_degree(xlon);
- wpt->description = xstrdup(cin);
-
- cx = strchr(comma, ')'); /* find tailing notes after the coordinates */
- if (cx != NULL) {
- char* tail = lrtrim(++cx);
- if (*tail != '\0') {
- wpt->notes = xstrdup(tail);
- }
- }
- /* generate some waypoints from our route-only format */
- if ((*cin != '-') && (case_ignore_strncmp(cin, "bei ", 4) != 0)) {
- waypt_add(waypt_dupe(wpt));
- }
-
- route_add_wpt(route, wpt);
- break;
- }
- xfree(buff);
- }
- }
-
- }
- cin = lend + 1;
- }
-}
-
-/* ============================================================================================
- * &&& gobal callbacks &&&
- * ----------------------------------------------------------------------------------------- */
-
-static void magpdb_rd_init(const char* fname)
-{
- file_in = pdb_open(fname, MYNAME);
-}
-
-static void magpdb_rd_deinit(void)
-{
- pdb_close(file_in);
-}
-
-static void magpdb_read(void)
-{
- pdbrec_t* pdb_rec;
-
- is_fatal((file_in->creator != PROUTE_MAGIC), /* identify the database */
- MYNAME ": Not a Map&Guide pdb file (0x%08x).", file_in->creator);
-
- is_fatal((file_in->version != 0), /* only version "0" currently seen and tested */
- MYNAME ": This file is from an unsupported version (%d) of Map&Guide and is unsupported.", file_in->version + 5);
-
- is_fatal((file_in->type != PROUTE_ROUTE),
- MYNAME ": Unknown pdb data type (0x%08x).", file_in->type);
-
- for (pdb_rec = file_in->rec_list; pdb_rec; pdb_rec = pdb_rec->next) {
- char* data = (char*)pdb_rec->data;
-
- if (be_read16(data) == 0) {
- int len = be_read16(data + 2);
- magpdb_read_data(data + 4, len);
- }
- }
-}
-
-/* ======================================================================================= */
-
-ff_vecs_t magpdb_vecs = {
- ff_type_file,
- { ff_cap_read, ff_cap_none, ff_cap_read }, /* real route + emulated waypoints */
- magpdb_rd_init,
- NULL,
- magpdb_rd_deinit,
- NULL,
- magpdb_read,
- NULL,
- NULL,
- magpdb_args,
- CET_CHARSET_MS_ANSI, 1 /* CET-REVIEW */
-};
-#endif
+++ /dev/null
-/*
- Read and write Magellan Navigator Companion files.
-
- Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
-
- */
-
-#include "defs.h"
-#if PDBFMTS_ENABLED
-#include "pdbfile.h"
-
-#define MYNAME "Companion Waypoints"
-#define MYTYPE 0x54777074 /* Twpt */
-#define MYCREATOR 0x4d47747a /* MGtz */
-
-struct record {
- pdb_16 crt_sec; /* Big endian, creation time */
- pdb_16 crt_min;
- pdb_16 crt_hour;
- pdb_16 crt_mday;
- pdb_16 crt_mon; /* 1 = Jan */
- pdb_16 crt_year; /* includes century. */
- pdb_16 unknown;
- pdb_16 xx_sec; /* appears to be time, but we don't know what it is. */
- pdb_16 xx_min;
- pdb_16 xx_hour;
- pdb_16 xx_mday;
- pdb_16 xx_mon;
- pdb_16 xx_year;
- pdb_16 unknown2;
- pdb_32 latitude; /* lat * 1e5 */
- pdb_32 longitude; /* lon * 1e5 */
- pdb_32 elevation; /* meters */
- char plot; /* 1 = plot on map screen. default = 0 */
- char unknown3; /* always 'a' */
-};
-
-static pdbfile* file_in;
-static pdbfile* file_out;
-static short_handle mkshort_handle;
-static int ct;
-
-static void
-rd_init(const char* fname)
-{
- file_in = pdb_open(fname, MYNAME);
-}
-
-static void
-rd_deinit(void)
-{
- pdb_close(file_in);
-}
-
-static void
-wr_init(const char* fname)
-{
- file_out = pdb_create(fname, MYNAME);
- mkshort_handle = mkshort_new_handle();
- setshort_length(mkshort_handle, 20);
- ct = 0;
-}
-
-static void
-wr_deinit(void)
-{
- pdb_close(file_out);
- mkshort_del_handle(&mkshort_handle);
-}
-
-static void
-data_read(void)
-{
- struct record* rec;
- pdbrec_t* pdb_rec;
-
- if ((file_in->creator != MYCREATOR) || (file_in->type != MYTYPE)) {
- fatal(MYNAME ": Not a Magellan Navigator file.\n");
- }
-
- for (pdb_rec = file_in->rec_list; pdb_rec; pdb_rec = pdb_rec->next) {
- waypoint* wpt_tmp;
- char* vdata;
- struct tm tm;
-
- memset(&tm, 0, sizeof(tm));
- wpt_tmp = waypt_new();
- rec = (struct record*) pdb_rec->data;
- wpt_tmp->altitude = be_read32(&rec->elevation);
-
- wpt_tmp->longitude = be_read32(&rec->longitude) / 1e5;
- wpt_tmp->latitude = be_read32(&rec->latitude) / 1e5;
-
- vdata = (char*) pdb_rec->data + sizeof(*rec);
-
- wpt_tmp->shortname = xstrdup(vdata);
- vdata += strlen(vdata) + 1;
-
- wpt_tmp->description = xstrdup(vdata);
- vdata += strlen(vdata) + 1;
-
- tm.tm_sec = be_read16(&rec->crt_sec);
- tm.tm_min = be_read16(&rec->crt_min);
- tm.tm_hour = be_read16(&rec->crt_hour);
- tm.tm_mday = be_read16(&rec->crt_mday);
- tm.tm_mon = be_read16(&rec->crt_mon) - 1;
- tm.tm_year = be_read16(&rec->crt_year) - 1900;
- if (mkgmtime(&tm) > 0) {
- wpt_tmp->SetCreationTime(mktime(&tm));
- }
- waypt_add(wpt_tmp);
-
- }
-}
-
-
-static void
-my_writewpt(const waypoint* wpt)
-{
- struct record* rec;
- char* vdata;
- const char* sn = global_opts.synthesize_shortnames ?
- mkshort_from_wpt(mkshort_handle, wpt) :
- wpt->shortname;
-
- rec = (struct record*) xcalloc(sizeof(*rec)+56,1);
-
- time_t tm_t;
- struct tm* tm;
- tm = NULL;
- if (wpt->creation_time.isValid()) {
- const time_t tt = wpt->creation_time.toTime_t();
- tm = gmtime(&tt);
- }
- if (!tm) {
- tm_t = current_time().toTime_t();
- tm = gmtime(&tm_t);
- }
-
- be_write16(&rec->crt_sec, tm->tm_sec);
- be_write16(&rec->crt_min, tm->tm_min);
- be_write16(&rec->crt_hour, tm->tm_hour);
- be_write16(&rec->crt_mday, tm->tm_mday);
- be_write16(&rec->crt_mon, tm->tm_mon + 1);
- be_write16(&rec->crt_year, tm->tm_year + 1900);
-
- be_write16(&rec->unknown, 0);
-
- be_write16(&rec->xx_sec, tm->tm_sec);
- be_write16(&rec->xx_min, tm->tm_min);
- be_write16(&rec->xx_hour, tm->tm_hour);
- be_write16(&rec->xx_mday, tm->tm_mday);
- be_write16(&rec->xx_mon, tm->tm_mon + 1);
- be_write16(&rec->xx_year, tm->tm_year + 1900);
-
- be_write16(&rec->unknown2, 0);
-
- be_write32(&rec->longitude, si_round(wpt->longitude * 100000.0));
- be_write32(&rec->latitude, si_round(wpt->latitude * 100000.0));
- be_write32(&rec->elevation, (unsigned int)(wpt->altitude));
-
- rec->plot = 0;
- rec->unknown3 = 'a';
-
- vdata = (char*)rec + sizeof(*rec);
- if (sn) {
- strncpy(vdata, sn, 21);
- vdata[20] = '\0';
- } else {
- vdata[0] ='\0';
- }
- vdata += strlen(vdata) + 1;
- if (wpt->description) {
- strncpy(vdata, wpt->description, 33);
- vdata[32] = '\0';
- } else {
- vdata[0] = '\0';
- }
- vdata += strlen(vdata) + 1;
- vdata[0] = '\0';
- vdata[1] = '\0';
- vdata += 2;
-
- pdb_write_rec(file_out, 0, 0, ct++, rec, (char*)vdata - (char*)rec);
-
- xfree(rec);
-}
-
-static void
-data_write(void)
-{
- static const char* appinfo =
- "\0\x01"
- "User\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\x01\x02\x03\x04\x05\x06\x07\x08"
- "\x09\x0a\x0b\x0c\x0d\x0e\x0f\0\0";
-
- strncpy(file_out->name, "Companion Waypoints", PDB_DBNAMELEN);
- file_out->attr = PDB_FLAG_BACKUP;
- file_out->ctime = file_out->mtime = current_time().toTime_t() + 2082844800U;
- file_out->type = MYTYPE; /* CWpt */
- file_out->creator = MYCREATOR; /* cGPS */
- file_out->version = 1;
- file_out->appinfo = (void*)appinfo;
- file_out->appinfo_len = 276;
-
- waypt_disp_all(my_writewpt);
-}
-
-
-ff_vecs_t magnav_vec = {
- ff_type_file,
- FF_CAP_RW_WPT,
- rd_init,
- wr_init,
- rd_deinit,
- wr_deinit,
- data_read,
- data_write,
- NULL,
- NULL,
- CET_CHARSET_ASCII, 0 /* CET-REVIEW */
-};
-#endif
+++ /dev/null
-/*
- Read and write Mapopolis files.
-
- Copyright (C) 2003 Robert Lipe, robertlipe@usa.net
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
-
- */
-
-#include "defs.h"
-#if PDBFMTS_ENABLED
-#include "pdbfile.h"
-
-#define MYNAME "Companion Waypoints"
-#define MYTYPE 0x64617461 /* Platdata */
-#define MYCREATOR 0x5061746c /* Plat */
-
-#define LONDIV (85116.044444)
-#define LATDIV (1000000.0/9)
-#define LONDIV2 (85116.044444/2)
-#define LATDIV2 (1000000.0/(9*2))
-
-
-struct record0 {
- char unk[6];
- pdb_32 lon1;
- pdb_32 lat1;
- pdb_32 lon2;
- pdb_32 lat2;
- pdb_32 lonD;
- pdb_32 latD;
- char name[31+1];
- char unk2[35];
- char demo;
- char unk3[4];
- unsigned char expcode[4];
- /* ... more stuff ... */
-};
-
-double Lat1, Lon1;
-double Lat2, Lon2;
-double LatD, LonD;
-
-struct record {
- char unknown[10];
- pdb_16 unk1;
- pdb_16 unk2;
- pdb_16 lon1d;
- pdb_16 lat1d;
- pdb_16 lon2d;
- pdb_16 lat2d;
-};
-
-static pdbfile* file_in, *file_out;
-static short_handle mkshort_handle;
-
-static void
-rd_init(const char* fname)
-{
- file_in = pdb_open(fname, MYNAME);
-}
-
-static void
-rd_deinit(void)
-{
- pdb_close(file_in);
-}
-
-static void
-wr_init(const char* fname)
-{
- file_out = pdb_create(fname, MYNAME);
- mkshort_handle = mkshort_new_handle();
- setshort_length(mkshort_handle, 20);
-}
-
-static void
-wr_deinit(void)
-{
- pdb_close(file_out);
- mkshort_del_handle(&mkshort_handle);
-}
-
-void convert_rec0(struct record0* rec0)
-{
- Lon1 = be_read32(&rec0->lon1) / LONDIV;
- Lat1 = be_read32(&rec0->lat1) / LATDIV;
- Lon2 = be_read32(&rec0->lon2) / LONDIV;
- Lat2 = be_read32(&rec0->lat2) / LATDIV;
- LonD = be_read32(&rec0->lonD) / LONDIV2;
- LatD = be_read32(&rec0->latD) / LATDIV2;
-
-// printf("%s: %.5f %.5f %.5f %.5f %.5f %.5f\n",
-// rec0->name, Lat1, Lon1, Lat2, Lon2, LatD, LonD);
-
-
-}
-
-/*
- * * Decode the information field
- * */
-void
-decode(char* buf)
-{
- int i;
-
- for (i = 0; buf[i]; ++i) {
- buf[i] = buf[i] ^ ((i % 96) & 0xf);
- }
-}
-
-static void
-data_read(void)
-{
- struct record* rec;
- pdbrec_t* pdb_rec;
-
- if ((file_in->creator != MYCREATOR) || (file_in->type != MYTYPE)) {
- fatal(MYNAME ": Not a Magellan Navigator file.\n");
- }
-
- pdb_rec = file_in->rec_list;
- convert_rec0((struct record0*) pdb_rec->data);
-
-// for(pdb_rec = pdb->rec_index.rec; pdb_rec; pdb_rec=pdb_rec->next) {
- for (pdb_rec = pdb_rec->next; pdb_rec; pdb_rec=pdb_rec->next) {
- waypoint* wpt_tmp;
- char* vdata = 0;
- char* edata;
- struct tm tm = {0};
-
- rec = (struct record*) pdb_rec->data;
- edata = (char*) rec + pdb_rec->size;
-
- for (; vdata < edata; rec = (struct record*) vdata) {
- wpt_tmp = waypt_new();
- wpt_tmp->latitude = Lat1 +
- be_read16(&rec->lat1d) / LATDIV2;
- wpt_tmp->longitude = Lon1 +
- be_read16(&rec->lon1d) / LONDIV2;
-
- vdata = (char*) rec + sizeof(*rec);
- wpt_tmp->description = xstrdup(vdata);
- vdata += strlen(wpt_tmp->description) + 1 + 6;
-
- while (*vdata == 0x40) {
- vdata++;
- }
- decode(vdata);
- wpt_tmp->notes = xstrdup(vdata);
- vdata += strlen(wpt_tmp->notes) + 1;
-
- waypt_add(wpt_tmp);
- }
- }
-}
-
-
-static void
-my_writewpt(const waypoint* wpt)
-{
-#if 0
- struct record* rec;
- static int ct;
- struct tm* tm;
- char* vdata;
- time_t tm_t;
- const char* sn = global_opts.synthesize_shortnames ?
- mkshort(mkshort_handle, wpt->description) :
- wpt->shortname;
-
- rec = xcalloc(sizeof(*rec)+56,1);
-
- tm = NULL;
- if (wpt->creation_time) {
- tm = gmtime(&wpt->creation_time);
- }
- if (!tm) {
- tm_t = current_time();
- tm = gmtime(&tm_t);
- }
-
- be_write16(&rec->crt_sec, tm->tm_sec);
- be_write16(&rec->crt_min, tm->tm_min);
- be_write16(&rec->crt_hour, tm->tm_hour);
- be_write16(&rec->crt_mday, tm->tm_mday);
- be_write16(&rec->crt_mon, tm->tm_mon + 1);
- be_write16(&rec->crt_year, tm->tm_mon + 1900);
-
- be_write16(&rec->unknown, 0);
-
- be_write16(&rec->xx_sec, tm->tm_sec);
- be_write16(&rec->xx_min, tm->tm_min);
- be_write16(&rec->xx_hour, tm->tm_hour);
- be_write16(&rec->xx_mday, tm->tm_mday);
- be_write16(&rec->xx_mon, tm->tm_mon + 1);
- be_write16(&rec->xx_year, tm->tm_mon + 1900);
-
- be_write16(&rec->unknown2, 0);
-
- be_write32(&rec->longitude, si_round(wpt->longitude * 100000.0));
- be_write32(&rec->latitude, si_round(wpt->latitude * 100000.0));
- be_write32(&rec->elevation, wpt->altitude);
-
- rec->plot = 0;
- rec->unknown3 = 'a';
-
- vdata = (char*)rec + sizeof(*rec);
- if (sn) {
- strncpy(vdata, sn, 21);
- vdata[20] = '\0';
- } else {
- vdata[0] ='\0';
- }
- vdata += strlen(vdata) + 1;
- if (wpt->description) {
- strncpy(vdata, wpt->description, 33);
- vdata[32] = '\0';
- } else {
- vdata[0] = '\0';
- }
- vdata += strlen(vdata) + 1;
- vdata[0] = '\0';
- vdata[1] = '\0';
- vdata += 2;
-
- pdb_write(file_out, 0, rec, (char*)vdata - (char*)rec);
-
- xfree(rec);
-#endif
-}
-
-static void
-data_write(void)
-{
- static char* appinfo =
- "\0\x01"
- "User\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\x01\x02\x03\x04\x05\x06\x07\x08"
- "\x09\x0a\x0b\x0c\x0d\x0e\x0f\0\0";
-
- strncpy(file_out->name, "Companion Waypoints", PDB_DBNAMELEN);
- file_out->name[PDB_DBNAMELEN-1] = 0;
- file_out->attr = PDB_FLAG_BACKUP;
- file_out->ctime = file_out->mtime = current_time() + 2082844800U;
- file_out->type = MYTYPE; /* CWpt */
- file_out->creator = MYCREATOR; /* cGPS */
- file_out->version = 1;
- file_out->appinfo = (void*)appinfo;
- file_out->appinfo_len = 276;
-
- waypt_disp_all(my_writewpt);
-}
-
-
-ff_vecs_t mapopolis_vecs = {
- ff_type_file,
- FF_CAP_RW_WPT,
- rd_init,
- wr_init,
- rd_deinit,
- wr_deinit,
- data_read,
- data_write,
- NULL,
- NULL,
- CET_CHARSET_ASCII, 0 /* CET-REVIEW */
-};
-#endif
+++ /dev/null
-/*
-
- Support for Microsoft AutoRoute 2002 ".axe" files,
-
- Copyright (C) 2005,2007,2008 Olaf Klein, o.b.klein@gpsbabel.org
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
-
-*/
-
-#include "defs.h"
-#include "jeeps/gpsmath.h"
-#include <ctype.h>
-
-#define MYNAME "msroute"
-
-#undef OLE_DEBUG
-
-static gbfile* fin;
-
-static arglist_t msroute_args[] = {
- ARG_TERMINATOR
-};
-
-/* MS-AutoRoute structures */
-
-typedef struct msroute_head_s {
- uint32_t U1; /* 58/02/00/00 */
- char masm[4]; /* "MASM " */
- uint32_t U2;
- uint32_t U3;
- int32_t waypts;
- uint32_t U5;
- uint32_t U6;
- uint32_t U7;
- uint32_t U8;
- uint32_t U9;
- uint32_t U10;
- uint32_t U11;
- uint32_t U12;
- uint32_t U13;
- uint32_t U14;
- uint32_t U15;
- uint32_t U16;
-// short U17;
-// char U18;
-} msroute_head_t;
-
-#define MSROUTE_OBJ_NAME "Journey"
-
-/* simple ole file reader */
-
-#define OLE_MAX_NAME_LENGTH 32
-#define OLE_HEAD_FAT1_CT (512-0x4c)/4
-
-#define BLOCKS(a, b) (((a) + (b) - 1) / (b))
-
-static const unsigned char ole_magic[8] = {
- 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1
-};
-
-/*
- The ole implementation looks like a FAT filesystem.
- Thatswhy i use in code fat1 as item for the "big blocks" or bbd
- and fat2 for "small blocks" (sbd).
-
- Remarks:
-
- * in the moment ole_size1 and sector_sz represents the same value
- * in OLE_DEBUG mode: successfully tested with 64MB++ standard MS doc's (PowerPoint, Word)
-*/
-
-typedef struct ole_head_s {
- char magic[8];
- char clsid[16];
- uint16_t rev; /* offset 0x18 */
- uint16_t ver; /* offset 0x1a */
- int16_t byte_order; /* offset 0x1c */
- uint16_t fat1_size_shift; /* offset 0x1e */
- uint16_t fat2_size_shift; /* offset 0x20 */
- uint16_t U7; /* offset 0x22 */
- uint32_t U8; /* offset 0x24 */
- uint32_t U9; /* offset 0x28 */
- int32_t fat1_blocks; /* offset 0x2c */
- int32_t prop_start; /* offset 0x30 */
- uint32_t U12; /* offset 0x34 */
- uint32_t fat1_min_size; /* offset 0x38 */
- int32_t fat2_start; /* offset 0x3c */
- int32_t fat2_blocks; /* offset 0x40 */
- int32_t fat1_extra_start; /* offset 0x44 */
- int32_t fat1_extra_ct; /* offset 0x48 */
- int32_t fat1[OLE_HEAD_FAT1_CT]; /* offset 0x4c */
-} ole_head_t;
-
-typedef struct ole_prop_s {
- uint16_t name[32];
- uint16_t name_sz; /* offset 0x40 */
- char ole_typ; /* offset 0x42 */
- char U1; /* offset 0x43 */
- uint32_t previous; /* offset 0x44 */
- uint32_t next; /* offset 0x48 */
- uint32_t dir; /* offset 0x4c */
- uint32_t U5; /* offset 0x50 */
- uint32_t U6; /* offset 0x54 */
- uint32_t U7; /* offset 0x58 */
- uint32_t U8; /* offset 0x5c */
- uint32_t U9; /* offset 0x60 */
- uint32_t U10; /* offset 0x64 */
- uint32_t U11; /* offset 0x68 */
- uint32_t U12; /* offset 0x6c */
- uint32_t U13; /* offset 0x70 */
- int32_t first_sector; /* offset 0x74 */
- int32_t data_sz; /* offset 0x78 */
- uint32_t U16; /* offset 0x7c */
-} ole_prop_t;
-
-#define DIR_ITEM_SIZE sizeof(ole_prop_t)
-
-static int sector_sz = 512;
-
-#ifndef min
-#define min(a,b) ((a) < (b)) ? (a) : (b)
-#endif
-#ifndef max
-#define max(a,b) ((a) > (b)) ? (a) : (b)
-#endif
-
-static int32_t* ole_fat1 = NULL;
-static int32_t* ole_fat2 = NULL;
-static int ole_fat1_ct;
-static int ole_fat2_ct;
-static int ole_size1;
-static int ole_size2;
-static int ole_size1_min = 4096;
-static ole_prop_t* ole_dir = NULL;
-static int ole_dir_ct;
-static ole_prop_t* ole_root = NULL;
-static char** ole_root_sec = NULL;
-static int ole_root_sec_ct;
-
-/* local helpers */
-
-static void
-le_read32_buff(int* buff, const int count)
-{
- int i;
- for (i = 0; i < count; i++) {
- buff[i] = le_read32(&buff[i]);
- }
-}
-
-/* simple OLE file reader */
-
-static void
-ole_read_sector(const int sector, void* target, const char full)
-{
- int res;
-
- res = gbfseek(fin, (sector + 1) * sector_sz, SEEK_SET);
- is_fatal((res != 0), MYNAME ": Could not seek file to sector %d!", sector + 1);
- res = gbfread(target, 1, sector_sz, fin);
- is_fatal(
- ((res < 0) || (full && (res < sector_sz))),
- MYNAME ": Read error (%d, sector %d) on file \"%s\"!", res, sector, fin->name);
-}
-
-static ole_prop_t*
-ole_find_property(const char* property)
-{
- int i;
-
- for (i = 0; i < ole_dir_ct; i++) {
- int len, test;
- char* str;
- ole_prop_t* item;
-
- item = &ole_dir[i];
- if ((item->ole_typ != 1) && (item->ole_typ != 2) && (item->ole_typ != 5)) {
- continue;
- }
- if ((item->data_sz <= 0) || (item->name_sz <= 0)) {
- continue;
- }
-
- len = min(OLE_MAX_NAME_LENGTH, item->name_sz / 2);
- str = cet_str_uni_to_utf8((short*)&item->name, len);
- test = case_ignore_strcmp(str, property);
- xfree(str);
-
- if (test == 0) {
- return item;
- }
- }
- is_fatal((1), MYNAME ": \"%s\" not in property catalog!", property);
- return 0;
-}
-
-static char*
-ole_read_stream(const ole_prop_t* property)
-{
- const char* action = "ole_read_stream";
- int len, sector, big, blocksize, offs, left;
- int i;
- int* fat;
- char* buff;
-
- len = property->data_sz;
-
- if (len >= ole_size1_min) {
- big = 1;
- blocksize = ole_size1;
- fat = ole_fat1;
- } else {
- big = 0;
- blocksize = ole_size2;
- fat = ole_fat2;
- }
-
- offs = 0;
- left = len;
- sector = property->first_sector;
-
- i = ((len + blocksize - 1) / blocksize) * blocksize;
- buff = (char*) xmalloc(i); /* blocksize aligned */
-
- if (big != 0) {
- while (left > 0) {
- int bytes = (left <= blocksize) ? left : blocksize;
- ole_read_sector(sector, buff + offs, (bytes >= sector_sz));
- left -= bytes;
- offs += bytes;
- if (left > 0) {
- sector = fat[sector];
- is_fatal((sector < 0), MYNAME ": Broken stream (%s)!", action);
- }
- }
- } else {
- int chain = sector;
- int blocks = (len + blocksize - 1) / blocksize;
- int blocks_per_sector = sector_sz / blocksize;
-
- offs = 0;
-
- while (blocks-- > 0) {
- char* temp;
- int block_offs;
-
- is_fatal((chain < 0), MYNAME ": Broken stream (%s)!", action);
-
- sector = chain / blocks_per_sector;
- is_fatal((sector >= ole_root_sec_ct), MYNAME ": Broken stream (%s)!", action);
-
- temp = ole_root_sec[sector];
- is_fatal((temp == NULL), MYNAME ": Broken stream (%s)!", action);
-
- block_offs = (chain % blocks_per_sector) * blocksize;
-
- memcpy(buff + offs, temp + block_offs, blocksize);
-
- offs += blocksize;
- chain = fat[chain];
- }
- }
- return buff;
-}
-
-
-static char*
-ole_read_property_stream(const char* property_name, int* data_sz)
-{
- ole_prop_t* property;
- char* result;
-
- if ((property = ole_find_property(property_name)) == NULL) {
- return NULL;
- }
-
- result = ole_read_stream(property);
- if ((result != NULL) && (data_sz != NULL)) {
- *data_sz = property->data_sz;
- }
-
- return result;
-}
-
-#ifdef OLE_DEBUG
-
-static void
-ole_test_properties()
-{
- int i;
-
- for (i = 0; i < ole_dir_ct; i++) {
- char* temp;
- char name[OLE_MAX_NAME_LENGTH + 1];
- ole_prop_t* p = &ole_dir[i];
-
- if ((p->ole_typ != 1) && (p->ole_typ != 2) && (p->ole_typ != 5)) {
- continue;
- }
- if ((p->data_sz <= 0) || (p->name_sz <= 0)) {
- continue;
- }
-
- temp = cet_str_uni_to_utf8(&p->name, min(p->name_sz / 2, OLE_MAX_NAME_LENGTH));
- strncpy(name, temp, sizeof(name));
- xfree(temp);
-
- printf(MYNAME ": ole_test_properties for \"%s\" (%d bytes):", name, p->data_sz);
-
- if ((case_ignore_strcmp(name, "Root Entry") == 0) ||
- (p->data_sz < ole_size1_min)) {
- printf(" skipped...\n");
- continue;
- } else {
- int sector = p->first_sector;
- int data_sz = p->data_sz;
- int block_size = ole_size1; /* sector_sz */
-
- printf("\n");
-
- while ((data_sz > 0) && (sector >= 0)) {
- int bytes = (data_sz > block_size) ? block_size : data_sz;
- int prev = sector;
-
- data_sz -= bytes;
- sector = ole_fat1[sector];
- if (sector == -3) {
- printf(MYNAME ": special block at %d\n", prev);
- if ((prev + 2) < ole_fat1_ct) {
- sector = ole_fat1[prev + 1];
- }
- printf(MYNAME "-new sector: %d\n", sector);
- }
- }
- is_fatal((data_sz != 0), MYNAME ": Error in fat1 chain, sector = %d, %d bytes (=%d blocks) left!",
- sector, data_sz, BLOCKS(data_sz, block_size));
- }
- }
-}
-#endif
-
-static void
-ole_init(void)
-{
- ole_head_t head;
- int i, i_offs, sector, count, left;
- int fat1_extra[128];
-
- ole_fat1 = NULL;
- ole_fat2 = NULL;
-
- sector_sz = 512; /* fixed for the moment */
-
- is_fatal((sizeof(head) != sector_sz),
- MYNAME ": (!) internal error - invalid header size (%lu)!",
- (unsigned long) sizeof(head));
-
- memset(&head, 0, sizeof(head));
- gbfread(&head, sizeof(head), 1, fin);
-
- is_fatal((strncmp(head.magic, (char*) ole_magic, sizeof(ole_magic)) != 0), MYNAME ": No MS document.");
-
- head.rev = le_read16(&head.rev);
- head.ver = le_read16(&head.ver);
- head.byte_order = le_read16(&head.byte_order);
- head.fat1_size_shift = le_read16(&head.fat1_size_shift);
- head.fat2_size_shift = le_read16(&head.fat2_size_shift);
- head.fat1_blocks = le_read32(&head.fat1_blocks);
- head.prop_start = le_read32(&head.prop_start);
- head.fat1_min_size = le_read32(&head.fat1_min_size);
- head.fat2_start = le_read32(&head.fat2_start);
- head.fat2_blocks = le_read32(&head.fat2_blocks);
- head.fat1_extra_start = le_read32(&head.fat1_extra_start);
- head.fat1_extra_ct = le_read32(&head.fat1_extra_ct);
- le_read32_buff(&head.fat1[0], OLE_HEAD_FAT1_CT);
-
- ole_size1 = (1 << head.fat1_size_shift);
- ole_size2 = (1 << head.fat2_size_shift);
- ole_size1_min = head.fat1_min_size;
-
-#ifdef OLE_DEBUG
- printf(MYNAME "-head: (version.revision) = %d.%d\n", head.ver, head.rev);
- printf(MYNAME "-head: byte-order = %d\n", head.byte_order);
- printf(MYNAME "-head: big fat start sector = %d (0x%x)\n", head.fat1[0], (head.fat1[0] + 1) * 512);
- printf(MYNAME "-head: big fat blocks = %d\n", head.fat1_blocks);
- printf(MYNAME "-head: big fat block size = %d\n", (1 << head.fat1_size_shift));
- printf(MYNAME "-head: small fat start sector = %d\n", head.fat2_start);
- printf(MYNAME "-head: small fat blocks = %d\n", head.fat2_blocks);
- printf(MYNAME "-head: small fat block size = %d\n", (1 << head.fat2_size_shift));
- printf(MYNAME "-head: big fat minimum length = %d\n", head.fat1_min_size);
- printf(MYNAME "-head: property catalog start sector = %d\n", head.prop_start);
- printf(MYNAME "-head: additional big fat blocks = %d\n", head.fat1_extra_ct);
- printf(MYNAME "-head: additional big fat start sector = %d (0x%x)\n", head.fat1_extra_start, (head.fat1_extra_start + 1) * 512);
-#endif
-
- is_fatal((head.byte_order != -2), MYNAME ": Unsupported byte-order %d", head.byte_order);
-#if 0
- sector_sz = ole_size1; /* i'll implement this, if i get an MS-doc (ole) */
- /* with "sector_sz" other than 512 */
-#else
- is_fatal((ole_size1 != 512), MYNAME ": Unsupported sector size %d", ole_size1);
-#endif
- ole_fat1 = (int32_t*) xmalloc(head.fat1_blocks * sector_sz);
- ole_fat1_ct = (head.fat1_blocks * sector_sz) / sizeof(int32_t);
-
-#ifdef OLE_DEBUG
- printf(MYNAME "-big fat: %d maximum sectors, size in memory %d, max. datasize %d bytes\n",
- ole_fat1_ct, head.fat1_blocks * sector_sz, head.fat1_blocks * sector_sz * sector_sz / sizeof(int32_t));
-#endif
-
- i_offs = 0; /* load "big fat" into memory */
- left = head.fat1_blocks;
- count = (left > OLE_HEAD_FAT1_CT) ? OLE_HEAD_FAT1_CT : left;
-
- for (i = 0; i < count; i++) {
- sector = head.fat1[i];
- ole_read_sector(sector, &ole_fat1[i_offs], 1);
- i_offs += ole_size1 / 4;
- }
-
- left -= count;
-
- if (left > 0) {
- sector = head.fat1_extra_start;
-
- while ((left > 0) && (sector >= 0)) {
- ole_read_sector(sector, &fat1_extra, 1);
- le_read32_buff(&fat1_extra[0], 128);
-
- count = (left < 127) ? left : 127;
- for (i = 0; i < count; i++) {
- ole_read_sector(fat1_extra[i], &ole_fat1[i_offs], 1);
- i_offs += ole_size1 / 4;
- }
- left -= count;
- if (left > 0) {
- sector = fat1_extra[127];
- }
- }
- is_fatal((left > 0), MYNAME ": Broken stream!");
- }
- if (ole_fat1_ct > 0) {
- le_read32_buff(&ole_fat1[0], ole_fat1_ct);
- }
-
-
- /* load fat2 "small fat" into memory */
-
- sector = head.fat2_start;
- if (sector >= 0) {
- count = 0;
- do {
- if (ole_fat2 == NULL) {
- ole_fat2 = (int*)xmalloc((count + 1) * sector_sz);
- } else {
- ole_fat2 = (int*)xrealloc(ole_fat2, (count + 1) * sector_sz);
- }
-
- ole_read_sector(sector, (char*)ole_fat2 + (count * sector_sz), 1);
- sector = ole_fat1[sector];
-
- count++;
- } while (sector >= 0);
-
- ole_fat2_ct = (count * sector_sz) / sizeof(int32_t);
- if (ole_fat2_ct > 0) {
- le_read32_buff(&ole_fat2[0], ole_fat2_ct);
- }
- }
-
- /* load directory (property catalog) */
-
- sector = head.prop_start;
- is_fatal((sector < 0), MYNAME ": Invalid file (no property catalog)!");
-
- count = 0;
- while (sector >= 0) {
- if (ole_dir == NULL) {
- ole_dir = (ole_prop_t*)xmalloc((count + 1) * sector_sz);
- } else {
- ole_dir = (ole_prop_t*)xrealloc(ole_dir, (count + 1) * sector_sz);
- }
-
- ole_read_sector(sector, (char*)ole_dir + (count * sector_sz), 1);
- sector = ole_fat1[sector];
-
- count++;
- }
- ole_dir_ct = (count * sector_sz) / sizeof(ole_prop_t);
-
- /* fix endianess of property catalog */
-
- for (i = 0; i < ole_dir_ct; i++) {
- ole_prop_t* item = &ole_dir[i];
-
- item->first_sector = le_read32(&item->first_sector);
- item->data_sz = le_read32(&item->data_sz);
- }
-
- ole_root = ole_find_property("Root Entry");
-
- /* read fat2 data sectors given by "Root Entry" */
-
- ole_root_sec_ct = (ole_root->data_sz + (sector_sz - 1)) / sector_sz;
- ole_root_sec = (char**) xcalloc(ole_root_sec_ct + 1, sizeof(char*));
-
- i = 0;
- sector = ole_root->first_sector;
- while (sector >= 0) {
- char* temp;
-
- temp = ole_root_sec[i++] = (char*) xmalloc(sector_sz);
-
- ole_read_sector(sector, temp, 1);
- sector = ole_fat1[sector];
- }
-#ifdef OLE_DEBUG
- ole_test_properties();
-#endif
-}
-
-static void
-ole_deinit(void)
-{
- if (ole_root_sec != NULL) {
- int i;
- for (i = 0; i < ole_root_sec_ct; i++) {
- char* c;
- if ((c = ole_root_sec[i])) {
- xfree(c);
- }
- }
- xfree(ole_root_sec);
- }
- if (ole_fat1 != NULL) {
- xfree(ole_fat1);
- }
- if (ole_fat2 != NULL) {
- xfree(ole_fat2);
- }
- if (ole_dir != NULL) {
- xfree(ole_dir);
- }
-}
-
-/* global MS AutoRoute functions */
-
-static void
-msroute_read_journey(void)
-{
- int bufsz = 0;
- char* buff;
-
- buff = ole_read_property_stream(MSROUTE_OBJ_NAME, &bufsz);
-
- if ((buff != NULL) && (bufsz > 0)) {
- msroute_head_t* head = (msroute_head_t*)buff;
- unsigned char* cin, *cend;
- int count = 0;
- route_head* route;
- waypoint* wpt;
- char version;
-
- is_fatal((strncmp(head->masm, "MASM", 4) != 0), MYNAME ": Invalid or unknown data!");
-
- version = buff[0x14];
- is_fatal((version < 1) || (version > 7), MYNAME ": Unsupported version %d!", version);
-
- cin = (unsigned char*)buff + 71; // (at least?) sizeof(msroute_head_t);
- cend = (unsigned char*)buff + bufsz;
-
- route = route_head_alloc();
- route_add_head(route);
-
- head->waypts = le_read32(&head->waypts);
-
- while (count < head->waypts) {
- int len;
-
- /* after version 6 we've seen data with different header length */
- /* now we try to find the next pair of names in buff */
-
- while (1) {
- len = *cin;
- if ((cin + 120) > cend) {
- cin = NULL;
- break;
- }
- if ((cin + len < cend) && /* within buff ? */
- (cin[len + 3] == 0xff) && /* 0xff before next length byte ? */
- (cin[len + 4] == len) && /* wide string of same length ? */
- (le_read16(cin + len + 1) == 0xfeff)) {
- break;
- }
- cin++;
- }
- if (cin == NULL) {
- break;
- }
-
- wpt = waypt_new();
-
- len = *cin++; /* length of shortname */
- cin += len;
- cin += 3; /* 0xfffeff */
-
- len = *cin++;
- wpt->shortname = cet_str_uni_to_utf8((const short*)cin, len);
- cin += (len * 2); /* seek over wide string */
- cin += (5 * sizeof(int32_t)); /* five unknown DWORDs */
-
- /* offs 12 !!!! Latitude int32 LE */
- /* offs 16 !!!! Longitude int32 LE */
- wpt->latitude = GPS_Math_Semi_To_Deg(le_read32(cin+12));
- wpt->longitude = GPS_Math_Semi_To_Deg(le_read32(cin+16));
-
- cin += (23 * sizeof(int32_t));
- cin += 3;
-
-#ifdef OLE_DEBUG
- waypt_add(waypt_dupe(wpt)); /* put to wpt-list to see results if no output is specified */
-#endif
- route_add_wpt(route, wpt);
- count++;
- }
- }
-
- if (buff != NULL) {
- xfree(buff);
- }
-}
-
-/* registered callbacks */
-
-static void msroute_rd_init(const char* fname)
-{
- fin = gbfopen(fname, "rb", MYNAME);
-
- ole_init();
-}
-
-static void msroute_rd_deinit(void)
-{
- ole_deinit();
-
- gbfclose(fin);
-}
-
-static void msroute_read(void)
-{
- msroute_read_journey();
-}
-
-ff_vecs_t msroute_vecs = {
- ff_type_file,
- { ff_cap_none, ff_cap_none, ff_cap_read },
- msroute_rd_init,
- NULL,
- msroute_rd_deinit,
- NULL,
- msroute_read,
- NULL,
- NULL,
- msroute_args,
- CET_CHARSET_UTF8, 1 /* CET-REVIEW */
-};
+++ /dev/null
-/*
- Output only format for PalmDoc
-
- Copyright (C) 2004 Scott Brynen, scott (at) brynen.com
- Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
- Copyright (C) 2004 Ronald L. Parker, ron@parkrrrr.com
- Portions from txt2pdbdoc, Copyright (C) 1998 Paul J. Lucas
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
-*/
-
-
-#include <ctype.h>
-#include <math.h>
-
-#include "defs.h"
-#if PDBFMTS_ENABLED
-#include "jeeps/gpsmath.h"
-#include "pdbfile.h"
-
-static pdbfile *file_out;
-static short_handle mkshort_handle;
-static short_handle mkshort_bookmark_handle;
-static const char *out_fname;
-
-static char *suppresssep = NULL;
-static char *dbname = NULL;
-static char *bmid = NULL;
-static char *includelogs = NULL;
-
-static int ct;
-static int offset;
-
-static char *palm_encrypt;
-
-#define MYNAME "PALMDOC"
-
-/* constants */
-#define BUFFER_SIZE 4096 /* big enough for uncompressed record */
-#define COMPRESSED 2
-#define COUNT_BITS 3 /* why this value? I don't know */
-#define DISP_BITS 11 /* ditto */
-
-#define DOC_CREATOR 0x52454164 /* "REAd" */
-#define DOC_TYPE 0x54455874 /* "TEXt" */
-#define UNCOMPRESSED 1
-
-struct buffer {
- unsigned char *data;
- unsigned len;
-};
-
-#define NEW_BUFFER(b) (b)->data = (unsigned char *)xmalloc( ((b)->len = 0,BUFFER_SIZE) )
-
-static
-arglist_t palmdoc_args[] = {
- {
- "nosep", &suppresssep,
- "No separator lines between waypoints", NULL,
- ARGTYPE_BOOL, ARG_NOMINMAX
- },
- {"dbname", &dbname, "Database name", NULL, ARGTYPE_STRING, ARG_NOMINMAX },
- {
- "encrypt", &palm_encrypt, "Encrypt hints with ROT13", NULL,
- ARGTYPE_BOOL, ARG_NOMINMAX
- },
- {
- "logs", &includelogs,
- "Include groundspeak logs if present", NULL, ARGTYPE_BOOL, ARG_NOMINMAX
- },
- {
- "bookmarks_short", &bmid, "Include short name in bookmarks",
- NULL, ARGTYPE_BOOL, ARG_NOMINMAX
- },
- ARG_TERMINATOR
-};
-
-static struct buffer buf;
-
-struct doc_record0 { /* 16 bytes total */
- uint16_t version; /* 1 = plain text, 2 = compressed */
- uint16_t reserved1;
- uint32_t doc_size; /* in bytes, when uncompressed */
- uint16_t num_records; /* PDB header numRecords - 1 */
- uint16_t rec_size; /* usually RECORD_SIZE_MAX */
- uint32_t reserved2;
- uint16_t recsizes[1];
-};
-
-static struct recordsize {
- int size;
- struct recordsize *next;
-} *recordsize_tail;
-
-static struct bookmark {
- int offset;
- char *text;
- struct bookmark *next;
-} *bookmark_tail;
-
-struct bookmark_record {
- char text[16];
- uint32_t offset;
-};
-
-static void put_byte(struct buffer *b, unsigned char c, int *space)
-{
- if (*space) {
- *space = 0;
- /*
- ** There is an outstanding space char: see if we can squeeze it
- ** in with an ASCII char.
- */
- if (c >= 0x40 && c <= 0x7F) {
- b->data[ b->len++ ] = c ^ 0x80;
- return;
- }
- b->data[ b->len++ ] = ' '; /* couldn't squeeze it in */
- } else if (c == ' ') {
- *space = 1;
- return;
- }
-
- if ((c >= 1 && c <= 8) || c >= 0x80) {
- b->data[ b->len++ ] = '\1';
- }
-
- b->data[ b->len++ ] = c;
-}
-
-static unsigned char * mem_find(unsigned char *t, int t_len, unsigned char *m, int m_len)
-{
- register int i;
- for (i = t_len - m_len + 1; i > 0; --i, ++t)
- if (*t == *m && !memcmp(t, m, m_len)) {
- return t;
- }
- return 0;
-}
-
-
-static void pd_compress(struct buffer *b)
-{
-
- unsigned i, j;
- int space = 0;
-
- unsigned char *buf_orig;
- unsigned char *p; /* walking test hit; works up on successive matches */
- unsigned char *p_prev;
- unsigned char *head; /* current test string */
- unsigned char *tail; /* 1 past the current test buffer */
- unsigned char *end; /* 1 past the end of the input buffer */
-
- p = p_prev = head = buf_orig = b->data;
- tail = head + 1;
- end = b->data + b->len;
-
- NEW_BUFFER(b);
- b->len = 0;
-
- /* loop, absorbing one more char from the input buffer on each pass */
- while (head != end) {
- /* establish where the scan can begin */
- if (head - p_prev > ((1 << DISP_BITS)-1)) {
- p_prev = head - ((1 << DISP_BITS)-1);
- }
-
- /* scan in the previous data for a match */
- p = mem_find(p_prev, tail - p_prev, head, tail - head);
-
- /* on a mismatch or end of buffer, issued codes */
- if (!p || p == head || tail - head > (1 << COUNT_BITS) + 2
- || tail == end
- ) {
- /* issued the codes */
- /* first, check for short runs */
- if (tail - head < 4) {
- put_byte(b, *head++, &space);
- } else {
- unsigned dist = head - p_prev;
- unsigned compound = (dist << COUNT_BITS)
- + tail - head - 4;
-
- /* for longer runs, issue a run-code */
- /* issue space char if required */
- if (space) {
- b->data[ b->len++ ] = ' ';
- space = 0;
- }
-
- b->data[ b->len++ ] = 0x80 + (compound >> 8);
- b->data[ b->len++ ] = compound & 0xFF;
- head = tail - 1;/* and start again */
- }
- p_prev = buf_orig; /* start search again */
- } else {
- p_prev = p; /* got a match */
- }
-
- /* when we get to the end of the buffer, don't inc past the */
- /* end; this forces the residue chars out one at a time */
- if (tail != end) {
- ++tail;
- }
- }
- xfree(buf_orig);
-
- if (space) {
- b->data[ b->len++ ] = ' '; /* add left-over space */
- }
-
- /* final scan to merge consecutive high chars together */
- for (i = j = 0; i < b->len; ++i, ++j) {
- b->data[ j ] = b->data[ i ];
-
- /* skip run-length codes */
- if (b->data[ j ] >= 0x80 && b->data[ j ] < 0xC0) {
- b->data[ ++j ] = b->data[ ++i ];
- }
-
- /* if we hit a high char marker, look ahead for another */
- else if (b->data[ j ] == '\1') {
- b->data[ j + 1 ] = b->data[ i + 1 ];
- while (i + 2 < b->len &&
- b->data[ i + 2 ] == 1 && b->data[ j ] < 8
- ) {
- b->data[ j ]++;
- b->data[ j + b->data[ j ] ] = b->data[ i + 3 ];
- i += 2;
- }
- j += b->data[ j ];
- ++i;
- }
- }
- b->len = j;
-}
-
-static void write_header(void)
-{
-
- int recs = ct-1;
- struct doc_record0 *rec0;
- --ct;
-
- rec0 = (struct doc_record0*) xcalloc(1, sizeof(struct doc_record0)+(ct-1)*sizeof(short));
- be_write16(&rec0->version, COMPRESSED);
- be_write16(&rec0->reserved1, 0);
- be_write32(&rec0->doc_size, offset);
- be_write16(&rec0->num_records, ct);
- be_write16(&rec0->rec_size, 4096);
- be_write32(&rec0->reserved2, 0);
- while (recs) {
- struct recordsize *oldrec = recordsize_tail;
- be_write16(&rec0->recsizes[recs], oldrec->size);
- recordsize_tail = oldrec->next;
- xfree(oldrec);
- --recs;
- }
-
- pdb_write_rec(file_out, 0, 0, 0, (void *)rec0, sizeof(struct doc_record0) + sizeof(short)*(ct-1));
-
- xfree(rec0);
-}
-
-static void write_bookmarks(void)
-{
- struct bookmark *oldmark = NULL;
- struct bookmark_record rec;
-
- struct bookmark *newtail = NULL;
-
- /* reverse the bookmark list */
- while (bookmark_tail) {
- oldmark = bookmark_tail;
- bookmark_tail = oldmark->next;
- oldmark->next = newtail;
- newtail = oldmark;
- }
- bookmark_tail = newtail;
-
- ct++;
- while (bookmark_tail) {
- oldmark = bookmark_tail;
- bookmark_tail = oldmark->next;
-
- be_write32(&rec.offset, oldmark->offset);
- memset(rec.text, 0, 16);
- strncpy(rec.text, oldmark->text, 16);
-
- pdb_write_rec(file_out, 0, 0, ct++, (void *)&rec, sizeof(struct bookmark_record));
-
- xfree(oldmark);
- }
-}
-
-static void commit_buffer(void)
-{
-
- struct recordsize *newrec = (struct recordsize*) xcalloc(1, sizeof(struct recordsize));
- newrec->next = recordsize_tail;
- newrec->size = buf.len;
- recordsize_tail = newrec;
-
- pd_compress(&buf);
-
- pdb_write_rec(file_out, 0, 0, ct++, (void *)buf.data, buf.len);
-}
-
-static void create_bookmark(char *bmtext)
-{
- struct bookmark *newmark = (struct bookmark *) xcalloc(1, sizeof(struct bookmark));
- newmark->next = bookmark_tail;
- newmark->offset = offset;
- newmark->text = bmtext;
- bookmark_tail = newmark;
-}
-
-static void docprintf(int maxlen, const char *format, ...)
-{
-
- char *txt = NULL;
- char *txt2 = NULL;
- va_list list;
- int newlen;
- int partlen;
-
- txt = (char *) xmalloc(maxlen);
-
- va_start(list, format);
- newlen = vsprintf(txt, format, list);
-
- txt2 = txt;
- offset += newlen;
- while (txt2 && *txt2) {
- /* append to buffer what we can */
- partlen = BUFFER_SIZE-1-buf.len;
- if (buf.len + newlen + 1 > BUFFER_SIZE) {
- strncpy((char *) buf.data+buf.len, txt2, partlen);
- buf.data[BUFFER_SIZE-1] = '\0';
- txt2 += partlen;
- newlen -= partlen;
- buf.len = BUFFER_SIZE-1;
- commit_buffer();
- NEW_BUFFER(&buf);
- } else {
- strcpy((char *) buf.data+buf.len, txt2);
- buf.len += newlen;
- txt2 = NULL;
- }
- }
-
- xfree(txt);
-}
-
-static void docfinish()
-{
- commit_buffer();
- write_header();
- write_bookmarks();
-}
-
-static void
-wr_init(const char *fname)
-{
- file_out = pdb_create(fname, MYNAME);
- out_fname = fname;
-
- mkshort_handle = mkshort_new_handle();
- mkshort_bookmark_handle = mkshort_new_handle();
- ct = 1;
- offset = 1;
- recordsize_tail = NULL;
- bookmark_tail = NULL;
- NEW_BUFFER(&buf);
-}
-
-static void
-wr_deinit(void)
-{
- pdb_close(file_out);
- mkshort_del_handle(&mkshort_handle);
- mkshort_del_handle(&mkshort_bookmark_handle);
-
- if (dbname) {
- xfree(dbname);
- dbname = NULL;
- }
-}
-
-static void
-palmdoc_disp(const waypoint *wpt)
-{
- int latint, lonint;
- char tbuf[1024];
- time_t tm = wpt->GetCreationTime().toTime_t();
- int32 utmz;
- double utme, utmn;
- char utmzc;
- char *bm;
- fs_xml *fs_gpx = NULL;
-
- char bookmarktext[17];
-
- if (bmid) {
- char * s = mkshort_from_wpt(mkshort_bookmark_handle, wpt);
- sprintf(bookmarktext, "%6s:%9s",
- wpt->shortname?wpt->shortname:"",s);
- xfree(s);
- } else {
- char * s = mkshort_from_wpt(mkshort_bookmark_handle, wpt);
- sprintf(bookmarktext, "%16s", s);
- xfree(s);
- }
-
- bm = xstrdup(bookmarktext);
- create_bookmark(bm);
-
- lonint = abs((int) wpt->longitude);
- latint = abs((int) wpt->latitude);
-
- GPS_Math_WGS84_To_UTM_EN(wpt->latitude, wpt->longitude,
- &utme, &utmn, &utmz, &utmzc);
-
- if (tm == 0) {
- tm = time(NULL);
- }
- strftime(tbuf, sizeof(tbuf), "%d-%b-%Y", localtime(&tm));
-
- docprintf(300, "%-16s %c%d %06.3f %c%d %06.3f (%d%c %6.0f %7.0f)",
- (global_opts.synthesize_shortnames) ? mkshort_from_wpt(mkshort_handle, wpt) : wpt->shortname,
- wpt->latitude < 0 ? 'S' : 'N', abs(latint), 60.0 * (fabs(wpt->latitude) - latint),
- wpt->longitude < 0 ? 'W' : 'E', abs(lonint), 60.0 * (fabs(wpt->longitude) - lonint),
- utmz, utmzc, utme, utmn);
- if (wpt->altitude != unknown_alt) {
- docprintf(100, " alt: %1.1f", wpt->altitude);
- }
- docprintf(10, "\n");
- if (strcmp(wpt->description, wpt->shortname)) {
- docprintf(10+strlen(wpt->description), "%s\n", wpt->description);
- }
- if (wpt->gc_data->terr) {
-
- docprintf(100, "%s/%s\n", gs_get_cachetype(wpt->gc_data->type),
- gs_get_container(wpt->gc_data->container));
-
- if (!wpt->gc_data->desc_short.utfstring.isEmpty()) {
- char *stripped_html = strip_html(&wpt->gc_data->desc_short);
- docprintf(10+strlen(stripped_html), "\n%s\n", stripped_html);
- xfree(stripped_html);
- }
- if (!wpt->gc_data->desc_long.utfstring.isEmpty()) {
- char *stripped_html = strip_html(&wpt->gc_data->desc_long);
- docprintf(10+strlen(stripped_html), "\n%s\n", stripped_html);
- xfree(stripped_html);
- }
- if (!wpt->gc_data->hint.isEmpty()) {
- char *hint = NULL;
- if (palm_encrypt) {
- hint = rot13(wpt->gc_data->hint);
- } else {
- hint = xstrdup(wpt->gc_data->hint.toUtf8().data());
- }
- docprintf(10+strlen(hint), "\nHint: %s\n", hint);
- xfree(hint);
- }
- } else if (wpt->notes && (!wpt->description || strcmp(wpt->notes,wpt->description))) {
- docprintf(10+strlen(wpt->notes), "%s\n", wpt->notes);
- }
-
- fs_gpx = NULL;
- if (includelogs) {
- fs_gpx = (fs_xml *)fs_chain_find(wpt->fs, FS_GPX);
- }
-
- if (fs_gpx && fs_gpx->tag) {
- xml_tag *root = fs_gpx->tag;
- xml_tag *curlog = NULL;
- xml_tag *logpart = NULL;
- curlog = xml_findfirst(root, "groundspeak:log");
- while (curlog) {
- time_t logtime = 0;
- struct tm *logtm = NULL;
- docprintf(10, "\n");
-
- logpart = xml_findfirst(curlog, "groundspeak:type");
- if (logpart) {
- docprintf(10+strlen(logpart->cdata), "%s by ", logpart->cdata);
- }
-
- logpart = xml_findfirst(curlog, "groundspeak:finder");
- if (logpart) {
- docprintf(10+strlen(logpart->cdata), "%s on ", logpart->cdata);
- }
-
- logpart = xml_findfirst(curlog, "groundspeak:date");
- if (logpart) {
- logtime = xml_parse_time(logpart->cdata).toTime_t();
- logtm = localtime(&logtime);
- if (logtm) {
- docprintf(15,
- "%2.2d/%2.2d/%4.4d\n",
- logtm->tm_mon+1,
- logtm->tm_mday,
- logtm->tm_year+1900
- );
- }
- }
-
- logpart = xml_findfirst(curlog, "groundspeak:log_wpt");
- if (logpart) {
- char *coordstr = NULL;
- float lat = 0;
- int latdeg = 0;
- float lon = 0;
- int londeg = 0;
- coordstr = xml_attribute(logpart, "lat");
- if (coordstr) {
- lat = atof(coordstr);
- }
- coordstr = xml_attribute(logpart, "lon");
- if (coordstr) {
- lon = atof(coordstr);
- }
- latdeg = abs(lat);
- londeg = abs(lon);
-
- docprintf(30,
- "%c %d\xb0 %.3f' %c %d\xb0 %.3f'\n",
-
- lat < 0 ? 'S' : 'N', latdeg, 60.0 * (fabs(lat) - latdeg),
- lon < 0 ? 'W' : 'E', londeg, 60.0 * (fabs(lon) - londeg)
- );
- }
-
- logpart = xml_findfirst(curlog, "groundspeak:text");
- if (logpart) {
- char *encstr = NULL;
- char *s = NULL;
- int encoded = 0;
- encstr = xml_attribute(logpart, "encoded");
- encoded = (toupper(encstr[0]) != 'F');
-
- if (palm_encrypt && encoded) {
- s = rot13(logpart->cdata);
- } else {
- s = xstrdup(logpart->cdata);
- }
-
- docprintf(5+strlen(s), "%s", s);
- xfree(s);
- }
-
- docprintf(10, "\n");
- curlog = xml_findnext(root, curlog, "groundspeak:log");
- }
- }
- if (! suppresssep) {
- docprintf(50, "---------------------------\n");
- } else {
- docprintf(10, "\n");
- }
-}
-
-static void
-data_write(void)
-{
- if (dbname) {
- strncpy(file_out->name, dbname, PDB_DBNAMELEN);
- } else {
- strncpy(file_out->name, out_fname, PDB_DBNAMELEN);
- }
- file_out->name[PDB_DBNAMELEN-1] = 0;
- file_out->attr = PDB_FLAG_BACKUP;
- file_out->ctime = file_out->mtime = current_time().toTime_t() + 2082844800U;
- file_out->type = DOC_TYPE;
- file_out->creator = DOC_CREATOR;
- file_out->version = 1;
-
- if (! suppresssep) {
- docprintf(50, "---------------------------\n");
- }
- setshort_length(mkshort_handle, 20);
- setshort_length(mkshort_bookmark_handle, 16-(bmid?7:0));
- setshort_whitespace_ok(mkshort_bookmark_handle, 0);
- waypt_disp_all(palmdoc_disp);
-
- docfinish();
-}
-
-
-ff_vecs_t palmdoc_vecs = {
- ff_type_file,
- { ff_cap_write, ff_cap_none, ff_cap_none},
- NULL,
- wr_init,
- NULL,
- wr_deinit,
- NULL,
- data_write,
- NULL,
- palmdoc_args,
- CET_CHARSET_ASCII, 0 /* CET-REVIEW */
-};
-
-
-#endif
+++ /dev/null
-/*
- Support for PathAway Palm Database,
- Copyright (C) 2005-2006 Olaf Klein, o.b.klein@gpsbabel.org
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
-
-*/
-
-/*
- remarks:
-
- The german release 3.0 of PathAway violates the PathAway standards:
- * N.. .... O.. .... instead of N.. .... E.. ....
- * date is formatted in DDMMYYYY instead of YYYYMMDD
-
- Release 4.x store only numeric coordinates and uses a six-number date.
-
- Modified by by Andrei Boros <slackware@andrix.ro> 2008-11-07
- * added information about database vehicle icon
- * Pathaway 4.x can handle invalid date/time and date format apparently
- has changed slightly between revisions :
- 131502.29 26102008 = HHMMSS.MS DDMMYYYY
- * work around errors reading date/time information
- (real life data collected by Pathaway sometimes has the date/time field
- contain some missing/invalid data. This information can be safely
- ignored most of the time. So far gpsbabel stopped processing files
- when encountering such invalid data)
- - date/time field may contain one or more spaces between fields
- - date/time field may start with one or more spaces
- - date/time field may contain invalid characters -> ignore
- - invalid or missing date/time -> ignore
- - only time may be present (some older versions of Pathaway 4)
-
- (this is still incomplete, but solved most of my problems when converting
- pathaway .pdb files)
-
-*/
-
-
-#include <ctype.h>
-#include <math.h>
-
-#include "defs.h"
-#if PDBFMTS_ENABLED
-#include "csv_util.h"
-#include "pdbfile.h"
-#include "strptime.h"
-
-#define MYNAME "pathaway"
-
-#define PPDB_MAGIC_TRK 0x55735472 /* UsTr */
-#define PPDB_MAGIC_WPT 0x506f4c69 /* PoLi */
-#define PPDB_MAGIC 0x4b6e5772 /* KwNr */
-
-#define VEHICLE_LEN 100
-
-static pdbfile *file_in, *file_out;
-static char *fname_out;
-static short_handle mkshort_handle;
-static gpsdata_type ppdb_type;
-static unsigned char german_release = 0;
-static char *datefmt;
-static int ct;
-static int warn_ = 0;
-
-typedef struct ppdb_appdata {
- unsigned char reservedA[274]; /* all 0 */
- unsigned char dirtyFlag;
- unsigned char dataBaseSubType; /* 0 = Track, 1 = Route */
- short int dbAttributes; /* 0 */
- char vehicleStr[VEHICLE_LEN];
- unsigned char reservedB[100]; /* all 0 */
-} ppdb_appdata_t;
-
-#define PPDB_APPINFO_SIZE sizeof(struct ppdb_appdata)
-static ppdb_appdata_t *appinfo;
-
-static char *opt_dbname = NULL;
-static char *opt_dbicon = NULL;
-static char *opt_deficon = NULL;
-static char *opt_snlen = NULL;
-static char *opt_date = NULL;
-
-static arglist_t ppdb_args[] = {
- {"date", &opt_date, "Read/Write date format (i.e. DDMMYYYY)", NULL, ARGTYPE_STRING, ARG_NOMINMAX},
- {"dbname", &opt_dbname, "Database name", NULL, ARGTYPE_STRING, ARG_NOMINMAX},
- {"dbicon", &opt_dbicon, "Database vehicle icon name", NULL, ARGTYPE_STRING, ARG_NOMINMAX},
- {"deficon", &opt_deficon, "Default icon name", NULL, ARGTYPE_STRING, ARG_NOMINMAX},
- {"snlen", &opt_snlen, "Length of generated shortnames", "10", ARGTYPE_INT, "1", NULL },
- ARG_TERMINATOR
-};
-
-/*#undef PPDB_DEBUG*/
-#define PPDB_DEBUG 1
-
-#if PPDB_DEBUG
-static void
-internal_debug1(const char *filename, int fileline)
-{
- static int ct=1;
- printf("DBG(%d): file %s, line %d: ", ct++, filename, fileline);
-}
-static void
-internal_debug2(const char *format, ...)
-{
- va_list args;
-
- va_start(args, format);
- vprintf(format, args);
- puts("");
- va_end(args);
-}
-#define DBG(args) internal_debug1(__FILE__, __LINE__);internal_debug2 args
-#else
-#define DBG(args) ;
-#endif
-
-
-#define CHECK_INP(i, j, k, l) is_fatal((i != j), "Error in data structure (in %s? Value is : %s).", (k), (l))
-
-/*
- * utilities
- */
-
-static
-char *ppdb_strcat(char *dest, const char *src, const char *def, int *size)
-{
- int len;
- char *res;
- const char *tmp;
-
- tmp = src;
- if (tmp == NULL) {
- tmp = def;
- if (tmp == NULL) {
- return dest;
- }
- }
- if (*tmp == '\0') {
- return dest;
- }
-
- len = strlen(dest) + strlen(tmp) + 1;
- if (len > *size) {
- *size = len;
- res = (char*) xrealloc(dest, *size);
- } else {
- res = dest;
- }
- strcat(res, tmp);
- return res;
-}
-
-#define STR_POOL_SIZE 16 /* !!! any power of 2 !!! */
-
-static char *str_pool[STR_POOL_SIZE];
-static size_t str_pool_s[STR_POOL_SIZE];
-static int str_poolp = -1;
-
-static
-void str_pool_init(void)
-{
- int i;
- for (i = 0; i < STR_POOL_SIZE; i++) {
- str_pool[i] = NULL;
- str_pool_s[i] = 0;
- }
-}
-
-static
-void str_pool_deinit(void)
-{
- int i;
-
- for (i = 0; i < STR_POOL_SIZE; i++)
- if (str_pool_s[i] != 0) {
- xfree(str_pool[i]);
- str_pool[i] = NULL;
- str_pool_s[i] = 0;
- }
-}
-
-static
-char *str_pool_get(size_t size)
-{
- char *tmp;
-
- str_poolp = ((str_poolp + 1) & (STR_POOL_SIZE - 1));
- tmp = str_pool[str_poolp];
-
- if (str_pool_s[str_poolp] == 0) {
- tmp = (char*) xmalloc(size);
- } else if (str_pool_s[str_poolp] < size) {
- tmp = (char*) xrealloc(tmp, size);
- } else {
- return tmp;
- }
-
- str_pool[str_poolp] = tmp;
- str_pool_s[str_poolp] = size;
-
- return tmp;
-}
-
-static
-char *str_pool_getcpy(const char *src, const char *def)
-{
- char *res;
-
- if (src == NULL) {
- src = def;
- if (src == NULL) {
- src = "";
- }
- }
- res = str_pool_get(strlen(src) + 1);
- strcpy(res, src);
-
- return res;
-}
-
-/*
- * decoding/formatting functions
- */
-
-static
-char *ppdb_fmt_float(const double val)
-{
- char *str = str_pool_get(32);
- char *c;
- snprintf(str, 32, "%.8f", val);
- c = str + strlen(str) - 1;
- while ((c > str) && (*c == '0')) {
- *c = '\0';
- c--;
- if (*c == '.') {
- c++;
- *c = '0';
- break;
- }
- }
- return str;
-}
-
-static
-char *ppdb_fmt_degrees(char dir, double val)
-{
- char *str = str_pool_get(32);
- int deg = fabs(val);
- double min = 60.0 * (fabs(val) - deg);
- char *tmp;
-
- snprintf(str, 31, "%c%0*d %.8f", dir, (deg > 99) ? 3 : 2, deg, min);
-
- tmp = str + strlen(str) - 1; /* trim trailing nulls */
- while ((tmp > str) && (*tmp == '0')) {
- *tmp = '\0';
- tmp--;
- if (*tmp == '.') {
- tmp++;
- *tmp = '0';
- break;
- }
- }
- return str;
-}
-
-static
-double ppdb_decode_coord(const char *str)
-{
- double val;
- int deg;
- char dir;
-
- if (*str < 'A') { /* only numeric */
- CHECK_INP(1, sscanf(str,"%lf", &val), "decode_coord(1) DD.dddd", str);
- return val;
- } else {
- const char *tmp;
-
- if (*str == 'O') {
- german_release = 1;
- }
-
- tmp = strchr(str, ' ');
- if ((tmp) && (tmp - str < 5)) {
- CHECK_INP(3, sscanf(str,"%c%d %lf", &dir, °, &val), "decode_coord(2) DD MM.mmm", str);
- val = deg + (val / 60.0);
- } else {
- CHECK_INP(2, sscanf(str,"%c%lf", &dir, &val), "decode_coord(3) DD.dddd", str);
- }
- if ((dir == 'S') || (dir == 'W')) {
- val = -val;
- }
- }
- return val;
-}
-
-static
-int ppdb_decode_tm(char *str, struct tm *tm)
-{
- int msec, d1, d2, d3, d4;
- int year;
- int temp=0;
- char *cx;
-
- str = lrtrim(str); /* time field may start/end with spaces, drop them */
-
- if (*str == '\0') {
- if (global_opts.debug_level > 0) {
- warning(MYNAME ": Time value missing, reseting to 0\n");
- warn_ = 1;
- }
- return 0; /* empty time field */
- }
-
- if (strchr(str, '.')) { /* time in hhmmss.ms */
- CHECK_INP(4, sscanf(str, "%02d%02d%02d.%d",
- &tm->tm_hour, &tm->tm_min, &tm->tm_sec, &msec),
- "decode_tm(1) hhmmss.ss", str);
- } else if (sscanf(str,"%06d",&temp)==1)
- /* WORKAROUND read time info only if a valid 6 digit string found */
- {
- CHECK_INP(3, sscanf(str, "%02d%02d%02d",
- &tm->tm_hour, &tm->tm_min, &tm->tm_sec),
- "decode_tm(2) hhmmss", str);
- } else {
- if (global_opts.debug_level > 0) {
- warning(MYNAME ": Invalid time value, reseting to 0\n");
- warn_ = 1;
- }
- return 0; /* WORKAROUND maybe invalid time, just ignore it and continue */
- }
- cx = strchr(str, ' ');
-
- if (cx == NULL) {
- if (global_opts.debug_level > 0) {
- warning(MYNAME ": Date value missing, reseting to 0\n");
- warn_ = 1;
- }
- return 0; /* empty date field */
- }
-
- cx = lrtrim(cx);
- if (*cx == '\0') {
- if (global_opts.debug_level > 0) {
- warning(MYNAME ": Date value missing, found only spaces, reseting to 0\n");
- warn_ = 1;
- }
- return 0; /* empty date field */
- }
-
- if (datefmt) {
- struct tm tm2;
-
- if (NULL == strptime(cx, datefmt, &tm2)) {
- fatal(MYNAME ": Unable to convert date '%s' using format '%s' (%s)!\n", cx, datefmt, opt_date);
- }
-
- tm->tm_year = tm2.tm_year + 1900;
- tm->tm_mon = tm2.tm_mon + 1;
- tm->tm_mday = tm2.tm_mday;
- } else {
- time_t tnow;
- struct tm now;
-
-
- tnow = current_time().toTime_t();
- now = *localtime(&tnow);
- now.tm_year += 1900;
- now.tm_mon++;
-
- if (strlen(cx) == 8) {
- CHECK_INP(4, sscanf(cx, "%02d%02d%02d%02d", &d1, &d2, &d3, &d4), "decode_tm(3) invalid date (YYYYMMDD)", cx);
-
- year = (d1 * 100) + d2;
- /* the coordinates comes before date and time in
- the dataset, so the flag "german_release" is set yet. */
-
- /* next code works for most, except for 19. and 20. of month */
-
- if ((german_release != 0) || (year < 1980) || (year > now.tm_year)) { /* YYYYMMDD or DDMMYYYY ????? */
- tm->tm_year = (d3 * 100) + d4;
- tm->tm_mon = d2;
- tm->tm_mday = d1;
- } else {
- tm->tm_year = (d1 * 100) + d2;
- tm->tm_mon = d3;
- tm->tm_mday = d4;
- }
- } else if (strlen(cx) == 6) {
- CHECK_INP(3, sscanf(cx, "%02d%02d%02d", &d1, &d2, &d3), "decode_tm(3) invalid date (DDMMYY)", cx);
- if (d3 < 1970) { /* Usual Y2K interpretation */
- year = d3 + 2000;
- } else {
- year = d3 + 1900;
- }
-
- /* I don't know how a german release handles this
- * so for now I will assume only DDMMYY if date has 6 digits
- */
- tm->tm_year = year;
- tm->tm_mon = d2;
- tm->tm_mday = d1;
- } else { /* date string is neither 8 nor 6 digits */
- printf(MYNAME ": Date from first record is %s.\n", cx);
- printf(MYNAME ": Please use option 'date' to specify how this is formatted.\n");
- fatal(MYNAME ": (... -i pathaway,date=DDMMYY ...)\n");
- }
- }
- return 1;
-}
-
-static
-int ppdb_read_wpt(route_head *head, int isRoute)
-{
- char *data, *str;
- double altfeet;
- struct tm tm;
-
- while (pdb_read_rec(file_in, NULL, NULL, NULL, (void **)&data) >= 0) {
- waypoint *wpt_tmp = waypt_new();
- int line = 0;
- char *tmp = data;
-
- /* Print the whole input record. All input records are printed before processing. */
- if (global_opts.debug_level >= 5) {
- DBG(("\n\
---- BEGIN Input data record -----------------------------------------------\n\
-%s\n\
---- END Input data record -------------------------------------------------\n",data));
- }
-
- while ((str = csv_lineparse(tmp, ",", "\"", line++))) {
- tmp = NULL;
- switch (line) {
- case 1: /* latitude */
- wpt_tmp->latitude = ppdb_decode_coord(str);
- break;
- case 2: /* longitude */
- wpt_tmp->longitude = ppdb_decode_coord(str);
- break;
- case 3: /* altitude */
- if (*str != '\0') {
- CHECK_INP(1, sscanf(str, "%lf", &altfeet), "altitude", str);
- if (altfeet != -9999) {
- wpt_tmp->altitude = FEET_TO_METERS(altfeet);
- }
- }
- break;
- case 4: /* time and date (optional) */
- memset(&tm, 0, sizeof(tm));
- if (ppdb_decode_tm(str, &tm)) {
- tm.tm_year -= 1900;
- tm.tm_mon--;
- wpt_tmp->SetCreationTime(mkgmtime(&tm));
- }
- break;
- case 5: /* name */
- if (*str != '\0') {
- wpt_tmp->shortname = xstrdup(str);
- }
- break;
- case 6: /* icon */
- if (*str != '\0') {
- wpt_tmp->icon_descr = str;
- }
- break;
- case 7: /* notes */
- if (*str != '\0') {
- wpt_tmp->notes = xstrdup(str);
- }
- break;
-
- }
- }
-
- /* Print the whole input record, should a warning be triggered.
- * Use warning() here instead of DBG() to print the data record
- * right after the warning is issued.
- */
- if (warn_ && (global_opts.debug_level > 1) && (global_opts.debug_level < 5)) {
- warning("Faulty input data record : %s\n",data);
- warn_ = 0;
- }
-
- if (head && isRoute) {
- route_add_wpt(head, wpt_tmp);
- } else if (head) {
- track_add_wpt(head, wpt_tmp);
- } else {
- waypt_add(wpt_tmp);
- }
-
- }
- return 0;
-}
-
-/* ============================================================================================
- * &&& gobal callbacks &&&
- * ----------------------------------------------------------------------------------------- */
-
-static void ppdb_rd_init(const char *fname)
-{
- str_pool_init();
- file_in = pdb_open(fname, MYNAME);
- ct = 0;
-
- if (opt_date) {
- datefmt = convert_human_date_format(opt_date);
- } else {
- datefmt = NULL;
- }
-}
-
-static void ppdb_rd_deinit(void)
-{
- pdb_close(file_in);
- str_pool_deinit();
- if (datefmt) {
- xfree(datefmt);
- }
-}
-
-static void ppdb_read(void)
-{
- ppdb_appdata_t *info = NULL;
- route_head *track_head, *route_head;
- const char *descr = NULL;
-
- if (file_in->creator != PPDB_MAGIC) { /* identify the database */
- fatal(MYNAME ": Not a PathAway pdb file.\n");
- }
-
- if (file_in->version != 3) { /* Currently we support only version 3 */
- fatal(MYNAME ": This file is from an untested version (%d) of PathAway and is unsupported.\n", file_in->version);
- }
-
- if ((file_in->appinfo_len > 0) && (file_in->appinfo != NULL)) {
- info = (ppdb_appdata_t *) file_in->appinfo;
- descr = info->vehicleStr;
- }
- switch (file_in->type) {
- case PPDB_MAGIC_TRK:
- ppdb_type = trkdata; /* as default */
- if (info != NULL) {
- switch (info->dataBaseSubType) {
- case 0:
- ppdb_type = trkdata;
- break;
- case 1:
- ppdb_type = rtedata;
- break;
- default:
- fatal(MYNAME": Invalid database subtype.\n");
- }
- }
- break;
-
- case PPDB_MAGIC_WPT:
- ppdb_type = wptdata;
- break;
-
- default:
- fatal(MYNAME ": It looks like a PathAway pdb, but has no gps magic.\n");
- }
-
- switch (ppdb_type) {
- case trkdata:
- track_head = route_head_alloc();
- track_add_head(track_head);
- track_head->rte_name = xstrdup(file_in->name);
- ppdb_read_wpt(track_head, 0);
- break;
- case rtedata:
- route_head = route_head_alloc();
- route_add_head(route_head);
- route_head->rte_name = xstrdup(file_in->name);
- ppdb_read_wpt(route_head, 1);
- break;
- case wptdata:
- case unknown_gpsdata:
- ppdb_read_wpt(NULL, 0);
- break;
- case posndata:
- fatal(MYNAME ": Realtime positioning not supported.\n");
- break;
- }
-}
-
-/* ============================================================================================
- * PPDB: Write support
- * -------------------------------------------------------------------------------------------*/
-
-static void ppdb_wr_init(const char *fname)
-{
- int len;
-
- fname_out = xstrdup(fname);
- str_pool_init();
- file_out = pdb_create(fname, MYNAME);
- mkshort_handle = mkshort_new_handle();
- ct = 0;
- appinfo = NULL;
-
- if (global_opts.synthesize_shortnames != 0) {
- len = atoi(opt_snlen);
- setshort_length(mkshort_handle, len);
- setshort_mustupper(mkshort_handle, 1);
- setshort_badchars(mkshort_handle, ",");
- setshort_whitespace_ok(mkshort_handle, 0);
- }
- if (opt_date) {
- char *c = convert_human_date_format(opt_date);
- xasprintf(&datefmt, "%s %s", "%H%M%S", c);
- xfree(c);
- } else {
- datefmt = xstrdup("%H%M%S %Y%m%d");
- }
-}
-
-static void ppdb_wr_deinit(void)
-{
- mkshort_del_handle(&mkshort_handle);
- pdb_close(file_out);
- str_pool_deinit();
- xfree(fname_out);
- if (datefmt) {
- xfree(datefmt);
- }
- if (appinfo) {
- xfree(appinfo);
- }
-}
-
-/*
- * ppdb_write_wpt: callback for waypoint output
- */
-
-#define REC_SIZE 128
-
-static void ppdb_write_wpt(const waypoint *wpt)
-{
- char *buff, *tmp;
- char latdir, longdir;
- int len;
- struct tm tm;
-
- buff = (char *) xcalloc(REC_SIZE, 1);
-
- if (wpt->latitude < 0) {
- latdir = 'S';
- } else {
- latdir = 'N';
- }
- if (wpt->longitude < 0) {
- longdir = 'W';
- } else {
- longdir = 'E';
- }
- /* 1 latitude,
- 2 longitude */
-
- snprintf(buff, REC_SIZE, "%s,%s,",
- ppdb_fmt_degrees(latdir, wpt->latitude),
- ppdb_fmt_degrees(longdir, wpt->longitude)
- );
-
- len = REC_SIZE; /* we have coordinates in buff, now optional stuff */
- /* 3 altitude */
-
- if (fabs(wpt->altitude) < 9999.0) {
- tmp = str_pool_get(32);
- snprintf(tmp, 32, "%s", ppdb_fmt_float(METERS_TO_FEET(wpt->altitude)));
- buff = ppdb_strcat(buff, tmp, NULL, &len);
- }
- buff = ppdb_strcat(buff, ",", NULL, &len);
- /* 4 time, date */
-
- if (wpt->creation_time.isValid()) {
- tmp = str_pool_get(20);
- const time_t tt = wpt->GetCreationTime().toTime_t();
- tm = *gmtime(&tt);
- strftime(tmp, 20, datefmt, &tm);
- buff = ppdb_strcat(buff, tmp, NULL, &len);
- }
- buff = ppdb_strcat(buff, ",", NULL, &len);
- /* 5 name */
-
- if (global_opts.synthesize_shortnames != 0) {
- tmp = mkshort_from_wpt(mkshort_handle, wpt);
- DBG(("shortname %s from %s", tmp, wpt->shortname));
- } else {
- tmp = str_pool_getcpy(wpt->shortname, "");
- while (strchr(tmp, ',') != NULL) {
- *strchr(tmp, ',') = '.';
- }
- }
- buff = ppdb_strcat(buff, tmp, "", &len);
-
- buff = ppdb_strcat(buff, ",", NULL, &len);
- /* 6 icon */
-
- tmp = str_pool_getcpy(wpt->icon_descr.toUtf8().data(), opt_deficon); /* point icon or deficon from options */
- buff = ppdb_strcat(buff, tmp, NULL, &len);
- buff = ppdb_strcat(buff, ",", NULL, &len);
- /* 7 description */
-
- tmp = str_pool_getcpy(wpt->description, "");
- if (strchr(tmp, ',') != NULL) {
- buff = ppdb_strcat(buff, "\"", NULL, &len);
- while (strchr(tmp, '"') != NULL) {
- *strchr(tmp, '"') = '\'';
- }
- buff = ppdb_strcat(buff, tmp, NULL, &len);
- buff = ppdb_strcat(buff, "\"", NULL, &len);
- } else {
- buff = ppdb_strcat(buff, tmp, "", &len);
- }
-
- len = strlen(buff) + 1;
- pdb_write_rec(file_out, 0, 0, ct++, buff, len);
-
- xfree(buff);
-}
-
-/*
- * track and route write callbacks
- */
-
-static void ppdb_write(void)
-{
-
- if (opt_dbname) {
- strncpy(file_out->name, opt_dbname, PDB_DBNAMELEN);
- }
-
- file_out->attr = PDB_FLAG_BACKUP;
- file_out->ctime = file_out->mtime = current_time().toTime_t() + 2082844800U;
- file_out->creator = PPDB_MAGIC;
- file_out->version = 3;
-
- /* Waypoint target does use vehicleStr from appinfo block
- * Actually, all 3 types have vehicle information.
- * if (global_opts.objective != wptdata) / * Waypoint target do not need appinfo block * /
- * {
- */
- appinfo = (ppdb_appdata_t *) xcalloc(1, sizeof(*appinfo));
- file_out->appinfo = (void *)appinfo;
- file_out->appinfo_len = PPDB_APPINFO_SIZE;
- /* }
- */
- if (opt_dbicon != NULL) {
- strncpy(appinfo->vehicleStr, opt_dbicon, VEHICLE_LEN);
- }
-
- switch (global_opts.objective) { /* Only one target is possible */
- case wptdata:
- case unknown_gpsdata:
- if (opt_dbname == NULL) {
- strncpy(file_out->name, "PathAway Waypoints", PDB_DBNAMELEN);
- }
- file_out->type = PPDB_MAGIC_WPT;
- waypt_disp_all(ppdb_write_wpt);
- break;
- case trkdata:
- if (opt_dbname == NULL) {
- strncpy(file_out->name, "PathAway Track", PDB_DBNAMELEN);
- }
- file_out->type = PPDB_MAGIC_TRK;
- appinfo->dataBaseSubType = 0;
- track_disp_all(NULL, NULL, ppdb_write_wpt);
- break;
- case rtedata:
- if (opt_dbname == NULL) {
- strncpy(file_out->name, "PathAway Route", PDB_DBNAMELEN);
- }
- file_out->type = PPDB_MAGIC_TRK;
- appinfo->dataBaseSubType = 1;
- route_disp_all(NULL, NULL, ppdb_write_wpt);
- break;
- case posndata:
- fatal(MYNAME ": Realtime positioning not supported.\n");
- break;
- }
-}
-
-
-ff_vecs_t ppdb_vecs = {
- ff_type_file,
- FF_CAP_RW_ALL,
- ppdb_rd_init,
- ppdb_wr_init,
- ppdb_rd_deinit,
- ppdb_wr_deinit,
- ppdb_read,
- ppdb_write,
- NULL,
- ppdb_args,
- CET_CHARSET_ASCII, 0 /* CET-REVIEW */
-};
-#endif
+++ /dev/null
-/*
-
- Minimum support for Palm/OS database files
- Copyright (C) 2007 Olaf Klein, o.b.klein@gpsbabel.org
-
- Written after study the Coldsync project
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
-
- */
-
-#include "defs.h"
-
-#if PDBFMTS_ENABLED
-
-#include "gbfile.h"
-#include "pdbfile.h"
-#include <stdio.h>
-#include <string.h>
-
-
-#define MYNAME "pdbfile"
-
-static void
-pdb_invalid_file(const pdbfile *pdb_in, const char *fmt, ...)
-{
- char buff[128];
- va_list args;
-
- va_start(args, fmt);
- vsnprintf(buff, sizeof(buff), fmt, args);
- buff[sizeof(buff)-1] = '0';
-
- warning(MYNAME ": %s\n", buff);
- fatal(MYNAME ": Invalid or unsupported file (%s).\n", pdb_in->file->name);
-}
-
-/* try to read to EOF (avoid determining file-size) */
-
-static void *
-pdb_read_tail(gbfile *fin, int32_t *size)
-{
- int count;
- char buff[256];
- char *res = NULL;
- int bytes = 0;
-
- while ((count = gbfread(buff, 1, sizeof(buff), fin))) {
-
- if (!res) {
- res = (char *) xmalloc(count);
- memcpy(res, buff, count);
- } else {
- res = (char*) xrealloc(res, bytes + count);
- memcpy(&res[bytes], buff, count);
- }
- bytes += count;
- }
- if (res) {
- res = (char*) xrealloc(res, bytes + 1);
- } else {
- res = (char*) xmalloc(1);
- }
- res[bytes] = '\0';
-
- if (size) {
- *size = bytes;
- }
- return (void *)res;
-}
-
-static void
-pdb_load_data(pdbfile *fin)
-{
- uint16_t i, ct;
- pdbrec_t *last_rec;
- uint32_t offs;
- pdbrec_t *rec;
-
- /* load the header */
- gbfread(fin->name, 1, PDB_DBNAMELEN, fin->file);
- fin->name[PDB_DBNAMELEN] = '\0';
-
- fin->attr = gbfgetuint16(fin->file);
- fin->version = gbfgetuint16(fin->file);
- fin->ctime = gbfgetuint32(fin->file);
- fin->mtime = gbfgetuint32(fin->file);
- fin->btime = gbfgetuint32(fin->file);
- fin->revision = gbfgetuint32(fin->file);
- fin->appinfo_offs = gbfgetint32(fin->file);
- fin->index_offs = gbfgetuint32(fin->file);
- fin->type = gbfgetuint32(fin->file);
- fin->creator = gbfgetuint32(fin->file);
- fin->uid = gbfgetuint32(fin->file);
-
- if (fin->appinfo_offs < 0) {
- pdb_invalid_file(fin, "Invalid application data offset (%0xh)", fin->appinfo_offs);
- }
- if (fin->index_offs < 0) {
- pdb_invalid_file(fin, "Invalid index offset (%0xh)", fin->index_offs);
- }
-
-#if 0
- fprintf(stderr, "%s: dbname \"%s\"\n", MYNAME, fin->name);
- fprintf(stderr, "%s: attr %-8x\n", MYNAME, fin->attr);
- fprintf(stderr, "%s: creator %-8x\n", MYNAME, fin->creator);
- fprintf(stderr, "%s: type %-8x\n", MYNAME, fin->type);
- fprintf(stderr, "%s: ver %-8u\n", MYNAME, fin->version);
- fprintf(stderr, "%s: app-ofs %-8u\n", MYNAME, fin->appinfo_offs);
- fprintf(stderr, "%s: index-ofs %-8u\n", MYNAME, fin->index_offs);
-#endif
- /* ID = */ (void) gbfgetuint32(fin->file);
- ct = fin->rec_ct = gbfgetint16(fin->file);
- if (ct >= 0x7FFF) {
- warning(MYNAME ": Probably invalid number of records (%0d)\n", fin->rec_ct);
- }
-
- offs = 78;
-
- last_rec = NULL;
- for (i = 0; i < ct; i++) {
- pdbrec_t *rec;
-
- rec = (pdbrec_t*) xcalloc(1, sizeof(*rec));
- if (fin->attr & PDB_FLAG_RESOURCE) {
- (void) gbfgetuint32(fin->file); /* type */
- rec->id = gbfgetint16(fin->file);
- rec->offs = gbfgetuint32(fin->file);
- if ((int32_t)rec->offs < 0) {
- pdb_invalid_file(fin, "Invalid offset to record (%0d, id = %d)", rec->offs, rec->id);
- }
- } else {
- uint32_t x;
-
- rec->offs = gbfgetint32(fin->file);
- x = gbfgetuint32(fin->file);
- rec->id = x & 0x0ffff;
- rec->category = (x >> 24) & 0x0f;
- rec->flags = (x >> 24) & 0xf0;
- if ((int32_t)rec->offs < 0) {
- pdb_invalid_file(fin, "Invalid offset to resource record (%0d, id = %d)", rec->offs, rec->id);
- }
- }
-
- if (last_rec == NULL) {
- fin->rec_list = rec;
- } else {
- last_rec->next = rec;
- }
- last_rec = rec;
- }
-
- offs += (ct * 8);
- last_rec = fin->rec_list;
-
- if (fin->appinfo_offs != 0) {
- uint32_t top;
-
- /* seek to application info offset */
- while (offs < fin->appinfo_offs) {
- (void)gbfgetc(fin->file);
- offs++;
- }
-
- /* determine the length of application info */
- if (fin->index_offs != 0) {
- top = fin->index_offs;
- } else {
- top = 0x7FFFFFFU;
- }
- if (last_rec && (last_rec->offs < top)) {
- top = last_rec->offs;
- }
-
- if (top != 0x7FFFFFFU) {
- fin->appinfo = xmalloc(top - offs);
- fin->appinfo_len = gbfread(fin->appinfo, 1, top - offs, fin->file);
- offs += fin->appinfo_len;
- } else {
- int32_t size;
- fin->appinfo = pdb_read_tail(fin->file, &size);
- fin->appinfo_len = size;
- offs += size;
- }
- }
-
- for (rec = fin->rec_list; rec; rec = rec->next) {
- /* seek to current record */
- while (offs < rec->offs) {
- (void) gbfgetc(fin->file);
- offs++;
- }
- if (rec->next) {
- rec->size = (int32_t)rec->next->offs - (int32_t)offs;
- if (rec->size > 0) {
- rec->data = (char*) xmalloc(rec->size);
- rec->size = gbfread(rec->data, 1, rec->size, fin->file);
- offs += rec->size;
- } else if (rec->size < 0) {
- pdb_invalid_file(fin, "Wrong data size in record with id %d.\n", rec->id);
- }
- } else {
- rec->data = (char*) pdb_read_tail(fin->file, &rec->size);
- offs += rec->size;
- }
- }
-}
-
-pdbfile *
-pdb_open(const char *filename, const char *module)
-{
- pdbfile *res;
-
- res = (pdbfile*) xcalloc(1, sizeof(*res));
- res->file = gbfopen_be(filename, "rb", module);
- res->mode = 1;
-
- pdb_load_data(res);
- pdb_rewind(res);
-
- return res;
-}
-
-int
-pdb_read_rec_by_id(pdbfile *fin, const uint32_t rec_id, uint8_t *flags, uint8_t *category, void **data)
-{
- pdbrec_t *rec;
-
- for (rec = fin->rec_list; rec; rec = rec->next) {
- if (rec->id == rec_id) {
- if (data) {
- *data = rec->data;
- }
- if (flags) {
- *flags = rec->flags;
- }
- if (category) {
- *category = rec->category;
- }
- return rec->size;
- }
- }
- return -1;
-}
-
-pdbfile *
-pdb_create(const char *filename, const char *module)
-{
- pdbfile *res;
-
- res = (pdbfile*) xcalloc(1, sizeof(*res));
- strncpy(res->name, "Palm/OS Database", PDB_DBNAMELEN);
- res->file = gbfopen_be(filename, "wb", module);;
- res->mode = 2;
-
- return res;
-}
-
-void
-pdb_write_rec(pdbfile *fout, const uint8_t flags, const uint8_t category, const uint32_t rec_id, const void *data, const uint32_t size)
-{
- pdbrec_t *rec, *cur;
-
- rec = (pdbrec_t*) xcalloc(1, sizeof(*rec));
- rec->category = category;
- rec->flags = category;
- rec->id = rec_id;
- rec->size = size;
- if (size > 0) {
- rec->data = (char*) xmalloc(size);
- memcpy(rec->data, data, size);
- }
-
- /* insert rec into rec_list sorted by id */
- cur = fout->rec_list;
- if (cur == NULL) {
- fout->rec_list = rec;
- } else {
- pdbrec_t *prev = NULL;
-
- while (cur) {
- if (rec_id < cur->id) {
- rec->next = cur;
- if (prev == NULL) {
- fout->rec_list = rec;
- } else {
- prev->next = rec;
- }
- break;
- } else if (rec_id == cur->id) { /* Overwrite record with id ... */
- rec->next = cur->next;
- if (prev == NULL) {
- fout->rec_list = rec;
- } else {
- prev->next = rec;
- }
- if (cur->data) {
- xfree(cur->data);
- }
- xfree(cur);
- cur = rec;
- break;
- }
- prev = cur;
- cur = cur->next;
- }
- if (! cur) {
- if (prev == NULL) {
- fout->rec_list = rec;
- } else {
- prev->next = rec;
- }
- }
- }
- fout->rec_ct++;
-}
-
-/* all data was buffered, write now to file */
-
-static void
-pdb_flush(pdbfile *file)
-{
- pdbrec_t *rec;
- gbfile *fout = file->file;
- int len, offs;
-
- offs = 78;
- file->index_offs = 0;
- offs += (file->rec_ct * 8);
-
- offs += 2;
-
- if (file->appinfo && (file->appinfo_len > 0)) {
- file->appinfo_offs = offs;
- offs += file->appinfo_len;
- } else {
- file->appinfo_offs = 0;
- }
-
- rec = file->rec_list;
- while (rec) { /* prepare data records */
- rec->offs = offs;
- offs += rec->size;
- rec = rec->next;
- }
-
- len = strlen(file->name);
- gbfwrite(file->name, 1, len, fout);
- while (len++ < PDB_DBNAMELEN) {
- gbfputc(0, fout);
- }
-
- gbfputuint16(file->attr, fout);
- gbfputuint16(file->version, fout);
- gbfputuint32(file->ctime, fout);
- gbfputuint32(file->mtime, fout);
- gbfputuint32(file->btime, fout);
- gbfputuint32(file->revision, fout);
- gbfputuint32(file->appinfo_offs, fout);
- gbfputuint32(file->index_offs, fout);
- gbfputuint32(file->type, fout);
- gbfputuint32(file->creator, fout);
- gbfputuint32(file->uid, fout);
-
- gbfputuint32(0, fout); /* ? ID ? */
- gbfputuint16(file->rec_ct, fout);
-
- for (rec = file->rec_list; rec; rec = rec->next) {
- uint32_t attr;
-
- gbfputint32(rec->offs, fout);
- attr = (rec->category & 0x0f) | (rec->flags & 0xf0);
- gbfputint32((rec->id & 0x0ffffff) | (attr << 24), fout);
- }
- gbfputint16(0, fout);
-
- if (file->appinfo && (file->appinfo_len > 0)) {
- gbfwrite(file->appinfo, 1, file->appinfo_len, fout);
- }
-
- for (rec = file->rec_list; rec; rec = rec->next) {
- if (rec->size > 0) {
- gbfwrite(rec->data, 1, rec->size, fout);
- }
- }
-}
-
-void
-pdb_close(pdbfile *file)
-{
- pdbrec_t *rec;
-
- if (! file) {
- return;
- }
-
- if (file->mode & 2) {
-#if 0
- /* this can be done later */
- if (gpsbabel_time == 0) { /* !!! We are in testo !!! */
- file->ctime = 0; /* (now we also can do a bincompare) */
- file->mtime = 0;
- file->btime = 0;
- }
-#endif
- pdb_flush(file);
- }
-
- gbfclose(file->file);
-
- if ((file->mode & 1) && file->appinfo) {
- xfree(file->appinfo);
- }
-
- rec = file->rec_list;
- while (rec) {
- pdbrec_t *tmp = rec;
- rec = rec->next;
-
- if (tmp->data) {
- xfree(tmp->data);
- }
- xfree(tmp);
- }
- xfree(file);
-}
-
-int
-pdb_eof(pdbfile *fin)
-{
- return (fin->rec_curr) ? 0 : 1;
-}
-
-int
-pdb_read_rec(pdbfile *fin, uint8_t *flags, uint8_t *category, uint32_t *rec_id, void **data)
-{
- if (pdb_eof(fin)) {
- return -1;
- } else {
- pdbrec_t *rec = fin->rec_curr;
- fin->rec_curr = rec->next;
-
- if (data) {
- *data = rec->data;
- }
- if (flags) {
- *flags = rec->flags;
- }
- if (category) {
- *category = rec->category;
- }
- if (rec_id) {
- *rec_id = rec->id;
- }
-
- return rec->size;
- }
-}
-
-void
-pdb_rewind(pdbfile *fin)
-{
- fin->rec_curr = fin->rec_list;
-}
-
-#endif
+++ /dev/null
-/*
- PocketStreets 2002 Pushpin Files
- Contributed to gpsbabel by Alex Mottram (geo_alexm at cox-internet.com)
-
- Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
-
- */
-
-#include "defs.h"
-#include "cet.h"
-#include "cet_util.h"
-#include <ctype.h>
-#include "grtcirc.h"
-
-#define MYNAME "PSP"
-
-#define MAXPSPSTRINGSIZE 256
-#define MAXPSPOUTPUTPINS 8192 /* Any more points than this is ludicrous */
-
-static gbfile *psp_file_in;
-static gbfile *psp_file_out;
-static short_handle mkshort_handle;
-
-#define psp_fread(b,s,m,f) gbfread((b),(s),(m),f)
-#define psp_fread_double(f) gbfgetdbl(f)
-#define psp_fwrite_double(v,f) gbfputdbl((v),f)
-
-/* ToDo: move the code inside to CET library */
-static void
-psp_write_str(const char *str)
-{
- if (str && *str) {
- short *unicode;
- int len;
-
- /* convert UTF-8 string into a unicode sequence */
- /* not perfect, but enough for us */
- unicode = cet_str_any_to_uni(str, global_opts.charset, &len);
- if (len > MAXPSPSTRINGSIZE) {
- len = MAXPSPSTRINGSIZE;
- }
- gbfputc((unsigned char)len, psp_file_out);
- if (len) {
- gbfwrite(unicode, 2, len, psp_file_out);
- }
-
- xfree(unicode);
- } else {
- gbfputc(0, psp_file_out);
- }
-}
-
-/* ToDo: move the code inside to CET library */
-static char *
-psp_read_str(gbfile *fin)
-{
- int len;
- int16_t *buff;
- char *res;
-
- len = (unsigned char)gbfgetc(fin);
- if (len == 0) {
- return NULL;
- }
-
- buff = (int16_t*) xmalloc(len * sizeof(*buff));
- gbfread(buff, sizeof(*buff), len, fin);
- res = cet_str_uni_to_utf8(buff, len);
- xfree(buff);
-
- return res;
-}
-
-/* Implement the grid in ascii art... This makes a bit of sense if you stand
- on a point over the north pole and look down on the earth.
-
--180 -90 0 90 180
------------------------------------- /\
-| 0x03 U|S 0x02 U|k 0x00 | 0x01 | 90
-|--------|--------|--------|--------| 0
-| 0x07 | 0x06 | 0x04 | 0x05 | -90
------------------------------------- \/
-*/
-static
-char grid_byte(double lat, double lon)
-{
- char c = 0x00;
-
- if ((lon >= 0.0) && (lon < 90.0)) {
- if (lat >= 0.0) {
- c = 0x00;
- } else {
- c = 0x04;
- }
- } else if (lon >= 90.0) {
- if (lat >= 0.0) {
- c = 0x01;
- } else {
- c = 0x05;
- }
- } else if ((lon < 0.0) && (lon >= -90.0)) {
- if (lat >= 0.0) {
- c = 0x02;
- } else {
- c = 0x06;
- }
- } else if (lon < -90.0) {
- if (lat >= 0.0) {
- c = 0x03;
- } else {
- c = 0x07;
- }
- }
-
- return (c);
-}
-
-void decode_psp_coordinates(double * lat, double * lon, const char lonbyte)
-{
- /* This is some sort of 1/2 Polar, 1/2 Cartesian coordinate mess in */
- /* the pin file. I really shouldn't have to do this. Zones 02 and 03 */
- /* work properly. The other zones are assumptions based on 02 and 03 */
-
- if ((lonbyte == 0x02) || (lonbyte == 0x06)) {
- /* one step west of zero longitude */
- if (*lon > 0.0) {
- *lon *= -1.0;
- }
- } else if ((lonbyte == 0x03) || (lonbyte == 0x07)) {
- /* two steps west of zero longitude */
- if (*lon > 0.0) {
- *lon -= 180.0;
- }
- } else if ((lonbyte == 0x00) || (lonbyte == 0x04)) {
- /* one step east of zero longitude */
- if (*lon < 0.0) {
- *lon *= -1.0;
- }
- } else if ((lonbyte == 0x01) || (lonbyte == 0x05)) {
- /* two steps east of zero longitude */
- if (*lon < 0.0) {
- *lon += 180.0;
- }
- }
-}
-
-static int
-valid_psp_header(char * header)
-{
- char header_bytes[] = { 0x31, 0x6E, 0x69, 0x50 }; /* 1niP <stop> */
-
- return (memcmp(header_bytes, header, 4));
-
-}
-
-static void
-psp_rd_init(const char *fname)
-{
- psp_file_in = gbfopen_le(fname, "rb", MYNAME);
-}
-
-static void
-psp_rd_deinit(void)
-{
- gbfclose(psp_file_in);
-}
-
-static void
-psp_wr_init(const char *fname)
-{
- psp_file_out = gbfopen_le(fname, "wb", MYNAME);
- mkshort_handle = mkshort_new_handle();
-}
-
-static void
-psp_wr_deinit(void)
-{
- mkshort_del_handle(&mkshort_handle);
- gbfclose(psp_file_out);
-}
-
-static void
-psp_read(void)
-{
- char buff[MAXPSPSTRINGSIZE + 1];
- double radians;
- double lat, lon;
- waypoint *wpt_tmp;
- short int pincount;
- short int pindex;
- char gridbyte = 0x00;
- char *tmp;
-
- /* 32 bytes - file header */
- psp_fread(&buff[0], 1, 32, psp_file_in);
-
- if (valid_psp_header(buff) != 0) {
- fatal(MYNAME ": input file does not appear to be a valid .PSP file.\n");
- }
-
- pincount = le_read16(&buff[12]);
-
- while (pincount--) {
- wpt_tmp = waypt_new();
-
- wpt_tmp->altitude = unknown_alt;
-
- /* offset 0x20 - 0x21 pin index */
- psp_fread(&pindex, 1, 2, psp_file_in);
-
- /* offset 0x22 - 0x23 */
- psp_fread(&buff[0], 1, 2, psp_file_in);
-
- /* offset 0x24 */
- /* 1 byte, the grid byte - needed for sign corrections later*/
- psp_fread(&gridbyte, 1, 1, psp_file_in);
-
- /* 8 bytes - latitude in radians */
- radians = psp_fread_double(psp_file_in);
- lat = DEG(radians);
-
- /* 8 bytes - longitude in radians */
- radians = psp_fread_double(psp_file_in);
- lon = DEG(radians);
-
- /* since we don't know the origin of this PSP file, we use */
- /* the grid byte adjust longitude, if necessary, mimicing */
- /* the behavior of pocketstreets correcting the data. This */
- /* does not correct the fact that points in eastern US are */
- /* written with the wrong coordinates by S&T. (MS bug) */
-
- decode_psp_coordinates(&lat, &lon, gridbyte);
-
- wpt_tmp->latitude = lat;
- wpt_tmp->longitude = lon;
-
- /* 1 byte - pin display properties */
- psp_fread(&buff[0], 1, 1, psp_file_in);
-
- /* 3 bytes - unknown */
- psp_fread(&buff[0], 1, 3, psp_file_in);
-
- /* 1 bytes - icon (values: 0x00 - 0x27) */
- psp_fread(&buff[0], 1, 1, psp_file_in);
-
- /* 3 bytes - unknown */
- psp_fread(&buff[0], 1, 3, psp_file_in);
-
- wpt_tmp->shortname = psp_read_str(psp_file_in);
- wpt_tmp->description = psp_read_str(psp_file_in);
- tmp = psp_read_str(psp_file_in); /* (address?) */
- if (tmp) {
- xfree(tmp);
- }
-
- waypt_add(wpt_tmp);
- }
-}
-
-static void
-psp_waypt_pr(const waypoint *wpt)
-{
- double lon, lat;
- char tbuf[64];
- char c;
- static short int pindex = 0;
- char *shortname;
- char *description;
-
- if ((! wpt->shortname) || (global_opts.synthesize_shortnames)) {
- if (wpt->description) {
- if (global_opts.synthesize_shortnames) {
- shortname = mkshort_from_wpt(mkshort_handle, wpt);
- } else {
- shortname = xstrdup(wpt->description);
- }
- } else {
- /* no description available */
- shortname = xstrdup("");
- }
- } else {
- shortname = xstrdup(wpt->shortname);
- }
-
- if (! wpt->description) {
- if (shortname) {
- description = xstrdup(shortname);
- } else {
- description = xstrdup("");
- }
- } else {
- description = xstrdup(wpt->description);
- }
-
- /* convert lat/long back to radians */
- lat = RAD(wpt->latitude);
- lon = RAD(wpt->longitude);
-
- pindex++;
- /* 2 bytes - pin index */
- gbfputint16(pindex, psp_file_out);
-
- /* 2 bytes - null bytes */
- gbfputint16(0, psp_file_out);
-
-
- /* set the grid byte */
- c = grid_byte(wpt->latitude,
- wpt->longitude);
-
- /* since the grid byte matches with what pocketstreets does to */
- /* input files, our output appears identical to a pin file that */
- /* has already been processed and corrected by pocketstreets. */
- /* Due to the grid and signs, it'll look different than one that */
- /* comes straight from S&T. */
-
- /* the grid byte */
- gbfwrite(&c, 1, 1, psp_file_out);
-
- /* 8 bytes - latitude/radians */
- psp_fwrite_double(lat, psp_file_out);
-
- /* 8 bytes - longitude/radians */
- psp_fwrite_double(lon, psp_file_out);
-
- /* 1 byte - pin properties */
- c = 0x14; /* display pin name on, display notes on. 0x04 = no notes */
- gbfwrite(&c, 1, 1, psp_file_out);
-
- memset(tbuf, '\0', sizeof(tbuf));
-
- /* 3 unknown bytes */
- gbfwrite(tbuf, 1, 3, psp_file_out);
-
- /* 1 icon byte 0x00 = PIN */
- gbfwrite(tbuf, 1, 1, psp_file_out);
-
- /* 3 unknown bytes */
- gbfwrite(tbuf, 1, 3, psp_file_out); /* 3 junk */
-
- psp_write_str(shortname);
- psp_write_str(description);
-
- /* just for the hell of it, we'll scrap the third string. */
- psp_write_str("");
-
- xfree(shortname);
- xfree(description);
-}
-
-static void
-psp_write(void)
-{
- short int s;
- unsigned char header_bytes[] = { 0x31, 0x6E, 0x69, 0x50, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
- /* the header: */
- /* 31 6E 69 50 20 00 00 00 08 00 00 00 11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */
- /* offset 0x0C - 0x0D = 2 byte pin count */
-
- s = waypt_count();
-
- if (global_opts.synthesize_shortnames) {
- setshort_length(mkshort_handle, 32);
- setshort_whitespace_ok(mkshort_handle, 1);
- }
-
- if (s > MAXPSPOUTPUTPINS) {
- fatal(MYNAME ": attempt to output too many pushpins (%d). The max is %d. Sorry.\n", s, MAXPSPOUTPUTPINS);
- }
-
- /* insert waypoint count into header */
- le_write16(&header_bytes[12], s);
-
- gbfwrite(header_bytes, 1, 32, psp_file_out);
-
- waypt_disp_all(psp_waypt_pr);
-}
-
-ff_vecs_t psp_vecs = {
- ff_type_file,
- FF_CAP_RW_WPT,
- psp_rd_init,
- psp_wr_init,
- psp_rd_deinit,
- psp_wr_deinit,
- psp_read,
- psp_write,
- NULL,
- NULL,
- CET_CHARSET_UTF8, 1 /* Fixed because of unicode strings in psp files (see psp_read_str / psp_write_str) */
-};
+++ /dev/null
-/*
- Read and write QuoVadis files.
-
- Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
-
- */
-
-#include "quovadis.h"
-
-#if PDBFMTS_ENABLED
-static pdbfile *file_in, *file_out;
-
-static uint8_t* rec_ptr = NULL;
-static uint8_t* current_rec = NULL;
-static int rec_index = 0;
-static int ct;
-static char *dbname = NULL;
-
-static
-arglist_t quovadis_args[] = {
- {"dbname", &dbname, "Database name", NULL, ARGTYPE_STRING, ARG_NOMINMAX},
- ARG_TERMINATOR
-};
-
-static struct qv_icon_mapping mapping[] = {
- { gt_unknown, QUESTION_ICON },
- { gt_traditional, HOSPITAL_ICON },
- { gt_multi, DOCUMENT_ICON },
- { gt_virtual, CAMERA_ICON },
- { gt_letterbox, MAILBOX_ICON },
- { gt_event, MEETING_ICON },
- { gt_suprise, GIFTSHOP_ICON },
-};
-
-#define num_mappings (sizeof(mapping) / sizeof(struct qv_icon_mapping))
-
-static geocache_type icon_to_wpt(int icon_bitmap)
-{
- unsigned int i;
-
- for (i = 0; i < num_mappings; i++) {
- if (icon_bitmap == mapping[i].bitmap_id) {
- return mapping[i].gc_type;
- }
- }
- return gt_unknown;
-}
-
-static int wpt_to_icon(geocache_type type)
-{
- unsigned int i;
-
- for (i = 0; i < num_mappings; i++) {
- if (type == mapping[i].gc_type) {
- return mapping[i].bitmap_id;
- }
- }
- return QUESTION_ICON;
-}
-
-static void
-rd_init(const char *fname)
-{
- file_in = pdb_open(fname, MYNAME);
-}
-
-static void
-rd_deinit(void)
-{
- pdb_close(file_in);
- if (dbname) {
- xfree(dbname);
- dbname = NULL;
- }
-}
-
-static void
-wr_init(const char *fname)
-{
- file_out = pdb_create(fname, MYNAME);
- ct = 0;
-}
-
-static void
-wr_deinit(void)
-{
- pdb_close(file_out);
- if (dbname) {
- xfree(dbname);
- dbname = NULL;
- }
-}
-
-static void
-data_read(void)
-{
- struct record *rec;
- pdbrec_t *pdb_rec;
- int i;
-
- if (!file_in->rec_list || (file_in->creator != MYCREATOR) || (file_in->type != MYTYPE)) {
- fatal(MYNAME ": Not a QuoVadis file.\n");
- }
-
- /* Ignore the first record, it contains one zero byte */
- for (pdb_rec = file_in->rec_list->next; pdb_rec; pdb_rec = pdb_rec->next) {
- int num_recs = pdb_rec->size / sizeof(struct record);
- for (i = 0; i < num_recs; i++) {
- waypoint *wpt_tmp;
-
- wpt_tmp = waypt_new();
-
- rec = (struct record *)
- &(pdb_rec->data[i * sizeof(struct record)]);
-
- wpt_tmp->longitude =
- (be_read32(&rec->longitude) / 1000000.0) - 180.0;
- wpt_tmp->latitude =
- 90.0 - (be_read32(&rec->latitude) / 1000000.0);
- wpt_tmp->shortname = xstrdup(rec->name);
-
- waypt_alloc_gc_data(wpt_tmp)->type =
- icon_to_wpt(be_read16(&rec->icon_bitmap));
-
- waypt_add(wpt_tmp);
- }
- }
-}
-
-
-static void
-quovadis_writewpt(waypoint *wpt)
-{
- struct record *rec;
- int i;
-
- if (current_rec == NULL) {
- uint8_t dummy = 0;
-
- pdb_write_rec(file_out, 0, 0, ct++, &dummy, 1);
-
- current_rec = (uint8_t *) xcalloc(MAXCHUNKSIZE, 1);
- rec_index = 0;
- rec_ptr = current_rec;
- }
-
- rec = (struct record *) xcalloc(sizeof(*rec),1);
-
- be_write32(&rec->longitude, (unsigned int)((wpt->longitude +
- 180.0) * 1000000.0));
- be_write32(&rec->latitude, (unsigned int)((90.0 - wpt->latitude) * 1000000.0));
- if (wpt->shortname) {
- strncpy(rec->name, wpt->shortname, 32);
- rec->name[31] = '\0';
- } else {
- rec->name[0] = '\0';
- }
- be_write16(&rec->icon_bitmap, wpt_to_icon(wpt->gc_data->type));
- be_write32(&rec->note_id, 0);
- rec->name_scale = DEFAULT_NAME_SCALE;
- rec->icon_scale = DEFAULT_ICON_SCALE;
- for (i = 0; i < 7; i++) {
- rec->reserved[i] = 0;
- }
-
- memcpy(rec_ptr, rec, sizeof(*rec));
- rec_ptr += sizeof(*rec);
- rec_index += 1;
- xfree(rec);
-
- if (rec_index == MAXRECORDS) {
- fatal(MYNAME ": cannot store more than %lu records at this time.\n",
- (unsigned long) MAXRECORDS);
- }
-}
-
-struct hdr {
- char *wpt_name;
- waypoint *wpt;
-};
-
-static
-int
-compare(const void *a, const void *b)
-{
- const struct hdr *wa = (const struct hdr *) a;
- const struct hdr *wb = (const struct hdr *) b;
-
- return strcmp(wa->wpt->shortname, wb->wpt->shortname);
-}
-
-static void
-data_write(void)
-{
- int i, ct = waypt_count();
- struct hdr *htable, *bh;
- queue *elem, *tmp;
- extern queue waypt_head;
- waypoint *waypointp;
-
- if (dbname) {
- strncpy(file_out->name, dbname, PDB_DBNAMELEN);
- } else {
- strncpy(file_out->name, "QuoVadisMarkerDB", PDB_DBNAMELEN);
- }
- file_out->name[PDB_DBNAMELEN-1] = 0;
- file_out->attr = PDB_FLAG_BACKUP;
- file_out->ctime = file_out->mtime = current_time().toTime_t() + 2082844800U;
- file_out->type = MYTYPE; /* CWpt */
- file_out->creator = MYCREATOR; /* cGPS */
- file_out->version = 1;
-
- /*
- * All this is to sort by waypoint names before going to QuoVadis.
- * Turns out plain old strcmp will do the trick...
- */
-
- htable = (struct hdr *) xmalloc(ct * sizeof(*htable));
- bh = htable;
-
- QUEUE_FOR_EACH(&waypt_head, elem, tmp) {
- waypointp = (waypoint *) elem;
- bh->wpt = waypointp;
- bh->wpt_name = waypointp->shortname;
- bh ++;
- }
- qsort(htable, ct, sizeof(*bh), compare);
-
- for (i=0; i<ct; i++) {
- quovadis_writewpt(htable[i].wpt);
- }
-
- if (rec_index != 0) {
- pdb_write_rec(file_out, 0, 0, ct++, current_rec, rec_index * sizeof(struct record));
- }
- xfree(current_rec);
-
- xfree(htable);
-}
-
-
-ff_vecs_t quovadis_vecs = {
- ff_type_file,
- FF_CAP_RW_WPT,
- rd_init,
- wr_init,
- rd_deinit,
- wr_deinit,
- data_read,
- data_write,
- NULL,
- quovadis_args,
- CET_CHARSET_ASCII, 0 /* CET-REVIEW */
-};
-#endif
+++ /dev/null
-/*
- Definitions for QuoVadis files.
-
- Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
-
- */
-#ifndef __quovadis_h__
-#define __quovadis_h__
-
-#include "defs.h"
-#include "pdbfile.h"
-
-#define MYNAME "QuoVadis"
-#define MYTYPE 0x51564D52 /* QVMR */
-#define MYCREATOR 0x51554F56 /* QUOV */
-
-#define MAXCHUNKSIZE 0x10000 /* 64k Chunk max */
-
-struct record {
- char name[32];
- pdb_32 longitude; /* Scaled. (degrees + 180.0) * 1e6 */
- pdb_32 latitude; /* Scaled. (degrees + 90.0) * 1e6 */
- pdb_16 icon_bitmap; /* Valid range: 0 - 47 */
- pdb_32 note_id; /* Global ID of note in NotesDB. Not
- supported yet */
- char name_scale; /* Map scale to display the
- name. Valid range 15-26. 15 =>
- 18.12 miles, 26 => 46 feet */
- char icon_scale; /* As above. */
- unsigned char reserved[8];
-};
-
-struct qv_icon_mapping {
- const geocache_type gc_type;
- const int bitmap_id;
-};
-
-/* Icon Types */
-#define QUESTION_ICON 0
-#define RESTARAUNT_ICON 1
-#define BAR_ICON 2
-#define HOTEL_ICON 3
-#define PHONE_ICON 4
-#define HOSPITAL_ICON 5
-#define CHURCH_ICON 6
-#define AIRPORT_ICON 7
-#define TRAIN_ICON 8
-#define BUS_ICON 9
-#define CAR_ICON 10
-#define WRENCH_ICON 11
-#define GASOLINE_ICON 12
-#define PARKING_ICON 13
-#define MAIL_ICON 14
-#define MAILBOX_ICON 15
-#define CLOCK_ICON 16
-#define FLAG_ICON 17
-#define LIBRARY_ICON 18
-#define BUILDINGS_ICON 19
-#define RELIGION_ICON 20
-#define DOCUMENT_ICON 21
-#define ANIMAL_ICON 22
-#define CAMERA_ICON 23
-#define MOVIE_ICON 24
-#define MUSIC_ICON 25
-#define MEETING_ICON 26
-#define RESTROOM_ICON 27
-#define FAMILY_ICON 28
-#define TELEVISION_ICON 29
-#define SAILING_ICON 30
-#define GOLF_ICON 31
-#define WORKOUT_ICON 32
-#define CYCLING_ICON 33
-#define JOGGING_ICON 34
-#define CAMPING_ICON 35
-#define WATER_ICON 36
-#define FOREST_ICON 37
-#define GIFTSHOP_ICON 38
-#define BABY_ICON 39
-#define LOVE_ICON 40
-#define CEMETARY_ICON 41
-#define COMPUTER_ICON 42
-#define MONEY_ICON 43
-#define LEFT_ARROW_ICON 44
-#define RIGHT_ARROW_ICON 45
-#define DOWN_ARROW_ICON 46
-#define UP_ARROW_ICON 47
-
-/* Scale Values */
-#define SCALE_18_12MI 15
-#define SCALE_9_06MI 16
-#define SCALE_4_53MI 17
-#define SCALE_2_26MI 18
-#define SCALE_1_13MI 19
-#define SCALE_0_56MI 20
-#define SCALE_0_28MU 21
-#define SCALE_747FT 22
-#define SCALE_373FT 23
-#define SCALE_186FT 24
-#define SCALE_93FT 25
-#define SCALE_46FT 26
-
-#define MAXRECORDS (MAXCHUNKSIZE / sizeof(struct record))
-/*#define MAXRECORDS 100*/
-#define DEFAULT_ICON_BITMAP QUESTION_ICON
-#define DEFAULT_NAME_SCALE SCALE_2_26MI
-#define DEFAULT_ICON_SCALE SCALE_18_12MI
-
-#endif
+++ /dev/null
-
-# Cetus GPS for PalmOS
-# This test is also similar to the NAV Companion test.
-rm -f ${TMPDIR}/cetus.pdb ${TMPDIR}/cetus.gpu ${TMPDIR}/cetust.gpu
-gpsbabel -i geo -f ${REFERENCE}/../geocaching.loc -o cetus -F ${TMPDIR}/cetus.pdb
-gpsbabel -i cetus -f ${TMPDIR}/cetus.pdb -o gpsutil -F ${TMPDIR}/cetus.gpu
-gpsbabel -i cetus -f ${REFERENCE}/cetus.pdb -o gpsutil -F ${TMPDIR}/cetust.gpu
-compare ${TMPDIR}/cetust.gpu ${TMPDIR}/cetus.gpu
-compare ${REFERENCE}/cetus.gpu ${TMPDIR}/cetus.gpu
-
-gpsbabel -i cetus -f ${REFERENCE}/track/cetus-track.pdb -o gpx -F ${TMPDIR}/cetus-track~gpx.gpx
-compare ${REFERENCE}/track/cetus-track~gpx.gpx ${TMPDIR}/cetus-track~gpx.gpx
+++ /dev/null
-
-#
-# CoastalExplorer..
-gpsbabel -r -i coastexp -f ${REFERENCE}/coastexp.nob -o gpx -F ${TMPDIR}/coastexp.gpx
-compare ${REFERENCE}/coastexp.ref ${TMPDIR}/coastexp.gpx
-gpsbabel -r -i gpx -f ${TMPDIR}/coastexp.gpx -o coastexp -F ${TMPDIR}/coastexp.nob
-compare ${REFERENCE}/coastexp.ref2 ${TMPDIR}/coastexp.nob
-gpsbabel -w -i coastexp -f ${REFERENCE}/coastexp.nob -o gpx -F ${TMPDIR}/coastexp.gpx
-compare ${REFERENCE}/coastexp.ref3 ${TMPDIR}/coastexp.gpx
-gpsbabel -w -i gpx -f ${TMPDIR}/coastexp.gpx -o coastexp -F ${TMPDIR}/coastexp.nob
-compare ${REFERENCE}/coastexp.ref4 ${TMPDIR}/coastexp.nob
-#
+++ /dev/null
-#
-# copilot
-#
-rm -f ${TMPDIR}/copilot.pdb
-gpsbabel -i copilot -f ${REFERENCE}/UKultralight.pdb -o copilot -F ${TMPDIR}/cop.pdb
-gpsbabel -i copilot -f ${REFERENCE}/UKultralight.pdb -o gpx -F ${TMPDIR}/cop1.gpx
-gpsbabel -i copilot -f ${TMPDIR}/cop.pdb -o gpx -F ${TMPDIR}/cop2.gpx
-compare ${TMPDIR}/cop1.gpx ${TMPDIR}/cop2.gpx
+++ /dev/null
-
-#
-# cotoGPS tests
-#
-rm -f ${TMPDIR}/coto*
-# Track reading
-gpsbabel -i coto -f ${REFERENCE}/cototesttrack.pdb -o xcsv,style=${REFERENCE}/cototest.style -F ${TMPDIR}/cototrack.csv
-compare ${REFERENCE}/cototesttrack.csv ${TMPDIR}/cototrack.csv
-# Marker read
-gpsbabel -i coto -f ${REFERENCE}/cototestmarker.pdb -o gpx -F ${TMPDIR}/cotomarker.gpx
-compare ${REFERENCE}/cototestmarker.gpx ${TMPDIR}/cotomarker.gpx
-# Marker write
-gpsbabel -i gpx -f ${REFERENCE}/cototestmarker.gpx -o coto -F ${TMPDIR}/cotomarker.pdb
-# bincompare ${REFERENCE}/cototestmarker.pdb ${TMPDIR}/cotomarker.pdb
-gpsbabel -i coto -f ${TMPDIR}/cotomarker.pdb -o gpx -F ${TMPDIR}/cotomarker.gpx
-compare ${REFERENCE}/cototestmarker.gpx ${TMPDIR}/cotomarker.gpx
-
--- /dev/null
+
+# Cetus GPS for PalmOS
+# This test is also similar to the NAV Companion test.
+rm -f ${TMPDIR}/cetus.pdb ${TMPDIR}/cetus.gpu ${TMPDIR}/cetust.gpu
+gpsbabel -i geo -f ${REFERENCE}/../geocaching.loc -o cetus -F ${TMPDIR}/cetus.pdb
+gpsbabel -i cetus -f ${TMPDIR}/cetus.pdb -o gpsutil -F ${TMPDIR}/cetus.gpu
+gpsbabel -i cetus -f ${REFERENCE}/cetus.pdb -o gpsutil -F ${TMPDIR}/cetust.gpu
+compare ${TMPDIR}/cetust.gpu ${TMPDIR}/cetus.gpu
+compare ${REFERENCE}/cetus.gpu ${TMPDIR}/cetus.gpu
+
+gpsbabel -i cetus -f ${REFERENCE}/track/cetus-track.pdb -o gpx -F ${TMPDIR}/cetus-track~gpx.gpx
+compare ${REFERENCE}/track/cetus-track~gpx.gpx ${TMPDIR}/cetus-track~gpx.gpx
--- /dev/null
+
+#
+# CoastalExplorer..
+gpsbabel -r -i coastexp -f ${REFERENCE}/coastexp.nob -o gpx -F ${TMPDIR}/coastexp.gpx
+compare ${REFERENCE}/coastexp.ref ${TMPDIR}/coastexp.gpx
+gpsbabel -r -i gpx -f ${TMPDIR}/coastexp.gpx -o coastexp -F ${TMPDIR}/coastexp.nob
+compare ${REFERENCE}/coastexp.ref2 ${TMPDIR}/coastexp.nob
+gpsbabel -w -i coastexp -f ${REFERENCE}/coastexp.nob -o gpx -F ${TMPDIR}/coastexp.gpx
+compare ${REFERENCE}/coastexp.ref3 ${TMPDIR}/coastexp.gpx
+gpsbabel -w -i gpx -f ${TMPDIR}/coastexp.gpx -o coastexp -F ${TMPDIR}/coastexp.nob
+compare ${REFERENCE}/coastexp.ref4 ${TMPDIR}/coastexp.nob
+#
--- /dev/null
+#
+# copilot
+#
+rm -f ${TMPDIR}/copilot.pdb
+gpsbabel -i copilot -f ${REFERENCE}/UKultralight.pdb -o copilot -F ${TMPDIR}/cop.pdb
+gpsbabel -i copilot -f ${REFERENCE}/UKultralight.pdb -o gpx -F ${TMPDIR}/cop1.gpx
+gpsbabel -i copilot -f ${TMPDIR}/cop.pdb -o gpx -F ${TMPDIR}/cop2.gpx
+compare ${TMPDIR}/cop1.gpx ${TMPDIR}/cop2.gpx
--- /dev/null
+
+#
+# cotoGPS tests
+#
+rm -f ${TMPDIR}/coto*
+# Track reading
+gpsbabel -i coto -f ${REFERENCE}/cototesttrack.pdb -o xcsv,style=${REFERENCE}/cototest.style -F ${TMPDIR}/cototrack.csv
+compare ${REFERENCE}/cototesttrack.csv ${TMPDIR}/cototrack.csv
+# Marker read
+gpsbabel -i coto -f ${REFERENCE}/cototestmarker.pdb -o gpx -F ${TMPDIR}/cotomarker.gpx
+compare ${REFERENCE}/cototestmarker.gpx ${TMPDIR}/cotomarker.gpx
+# Marker write
+gpsbabel -i gpx -f ${REFERENCE}/cototestmarker.gpx -o coto -F ${TMPDIR}/cotomarker.pdb
+# bincompare ${REFERENCE}/cototestmarker.pdb ${TMPDIR}/cotomarker.pdb
+gpsbabel -i coto -f ${TMPDIR}/cotomarker.pdb -o gpx -F ${TMPDIR}/cotomarker.gpx
+compare ${REFERENCE}/cototestmarker.gpx ${TMPDIR}/cotomarker.gpx
+
--- /dev/null
+
+#
+# Geocaching Database is a binary Palm format that, like the GPX variants
+# has a zillion "equivalent" encodings of any given record set. So we
+# read the reference file, spin it to GPX and back to GCDB and then spin
+# that one to GPX.
+#
+
+gpsbabel -i gcdb -f ${REFERENCE}/GeocachingDB.PDB -o gpx -F ${TMPDIR}/gcdb1.gpx \
+ -o gcdb -F ${TMPDIR}/gcdb1.pdb
+gpsbabel -i gpx -f ${TMPDIR}/gcdb1.gpx -o gpx -F ${TMPDIR}/gcdb2.gpx
+compare ${TMPDIR}/gcdb1.gpx ${TMPDIR}/gcdb1.gpx
+
--- /dev/null
+#
+# Geoniche: No reference file was available, so we created one and just
+# test it against itself.
+#
+rm -f ${TMPDIR}/gn.pdb ${TMPDIR}/1.gpx ${TMPDIR}/2.gpx
+gpsbabel -i geoniche -f ${REFERENCE}/geoniche.pdb -o geoniche -F ${TMPDIR}/gn.pdb
+gpsbabel -i geoniche -f ${REFERENCE}/geoniche.pdb -o gpx -F ${TMPDIR}/1.gpx
+gpsbabel -i geoniche -f ${TMPDIR}/gn.pdb -o gpx -F ${TMPDIR}/2.gpx
+compare ${TMPDIR}/1.gpx ${TMPDIR}/2.gpx
+#
+gpsbabel -i geoniche -f ${REFERENCE}/gn-targets.pdb -o gpx -F ${TMPDIR}/gn-targets.gpx
+compare ${REFERENCE}/gn-targets.gpx ${TMPDIR}/gn-targets.gpx
--- /dev/null
+
+#
+# GPilotS. A Palm format. Another binary format that
+#
+# rm -f ${TMPDIR/gpilots.l
+#gpsbabel -i easygps -f ${REFERENCE}/gpilots.pdb -o gpx -F ${TMPDIR}/gp.gpx
+gpsbabel -i geo -f ${REFERENCE}/../geocaching.loc -o gpilots -F ${TMPDIR}/blah.pdb
+gpsbabel -i gpilots -f ${TMPDIR}/blah.pdb -o gpx -F ${TMPDIR}/1.gpx
+gpsbabel -i gpilots -f ${REFERENCE}/gpilots.pdb -o gpx -F ${TMPDIR}/2.gpx
+compare ${TMPDIR}/1.gpx ${TMPDIR}/2.gpx
+#gpsbabel -i easygps -f ${REFERENCE}/gpilots.pdb -o gpx -F ${TMPDIR}/gp.gpx
+
--- /dev/null
+# GPSPilot Tracker for PalmOS
+# This test is eerily similar to the NAV Companion test. In fact, the
+# converted reference file (magnavr.gpu) is identical.
+rm -f ${TMPDIR}/gpspilot.pdb ${TMPDIR}/gpspilot.gpu ${TMPDIR}/gpspil_t.gpu
+gpsbabel -i geo -f ${REFERENCE}/../geocaching.loc -o gpspilot -F ${TMPDIR}/gpspilot.pdb
+gpsbabel -i gpspilot -f ${TMPDIR}/gpspilot.pdb -o gpsutil -F ${TMPDIR}/gpspilot.gpu
+gpsbabel -i gpspilot -f ${REFERENCE}/gpspilot.pdb -o gpsutil -F ${TMPDIR}/gpspil_t.gpu
+compare ${TMPDIR}/gpspil_t.gpu ${TMPDIR}/gpspilot.gpu
+compare ${REFERENCE}/gu.wpt ${TMPDIR}/gpspilot.gpu
--- /dev/null
+# hsandv
+rm -f ${TMPDIR}/hsandv.exp ${TMPDIR}/1.exp ${TMPDIR}/1.exp ${TMPDIR}/Glad_5.exp
+gpsbabel -i geo -f ${REFERENCE}/../geocaching.loc -o hsandv -F ${TMPDIR}/hsandv.exp
+compare ${TMPDIR}/hsandv.exp ${REFERENCE}
+#the hsandv format is too lossy to do this test :(
+#gpsbabel -i hsandv -f ${TMPDIR}/hsandv.exp -o geo -F ${TMPDIR}/1.exp
+#gpsbabel -i hsandv -f ${REFERENCE}/hsandv.exp -o geo -F ${TMPDIR}/2.exp
+#compare ${TMPDIR}/1.exp ${TMPDIR}/2.exp
+#test conversion from v4 to v5 files
+gpsbabel -i hsandv -f ${REFERENCE}/Glad_4.exp -o hsandv -F ${TMPDIR}/Glad_5.exp
+# FIXME: Can't compare directly because of potential FP rounding.
+# FIXME: compare ${TMPDIR}/Glad_5.exp reference
--- /dev/null
+#
+# Map&Guide Palm/OS .pdb files (read-only)
+#
+rm -f ${TMPDIR}/mag_pdb-*
+gpsbabel -i mag_pdb -f ${REFERENCE}/route/mag_pdb-sample.pdb -o gpx -F ${TMPDIR}/mag_pdb-sample.gpx
+compare ${REFERENCE}/route/mag_pdb-sample.gpx ${TMPDIR}/mag_pdb-sample.gpx
+
--- /dev/null
+# Magellan NAV Companion for PalmOS
+# This format is hard to test, because each record and the database itself
+# contains the time of creation, so two otherwise identical files won't
+# compare accurately. In any case, the files are binary so compare wouldn't
+# like them. So, we convert the reference file to gpsutil and the converted
+# file to gpsutil and make sure they're the same, and that they're the same
+# as one converted on a known-working installation. Unfortunately, this does
+# not verify that the appinfo block was written correctly. However, it does
+# successfully test for some endianness errors that might otherwise go
+# unnoticed.
+rm -f ${TMPDIR}/magnav.pdb ${TMPDIR}/magnav.gpu ${TMPDIR}/magnavt.gpu
+gpsbabel -i geo -f ${REFERENCE}/../geocaching.loc -o magnav -F ${TMPDIR}/magnav.pdb
+gpsbabel -i magnav -f ${TMPDIR}/magnav.pdb -o gpsutil -F ${TMPDIR}/magnav.gpu
+gpsbabel -i magnav -f ${REFERENCE}/magnav.pdb -o gpsutil -F ${TMPDIR}/magnavt.gpu
+compare ${TMPDIR}/magnavt.gpu ${TMPDIR}/magnav.gpu
+compare ${REFERENCE}/gu.wpt ${TMPDIR}/magnav.gpu
+
+rm -f ${TMPDIR}/magnav.pdb
+gpsbabel -i geo -f ${REFERENCE}/../geocaching.loc -o magnav -F ${TMPDIR}/magnav.pdb
+bincompare ${TMPDIR}/magnav.pdb ${REFERENCE}/magnav.pdb
+
--- /dev/null
+#
+# Microsoft AutoRoute 2002 test (read-only)
+#
+gpsbabel -i msroute -f ${REFERENCE}/route/msroute-sample.axe -o gpx -F ${TMPDIR}/msroute-sample.gpx
+compare ${REFERENCE}/route/msroute-sample.gpx ${TMPDIR}/msroute-sample.gpx
+
--- /dev/null
+#
+# PathAway Palm Database .pdb tests
+#
+rm -f ${TMPDIR}/pathaway*
+gpsbabel -i geo -f ${REFERENCE}/../geocaching.loc -o pathaway,dbname="pathaway-geo" -F ${TMPDIR}/pathaway-geo.pdb
+gpsbabel -i pathaway -f ${TMPDIR}/pathaway-geo.pdb -o geo -F ${TMPDIR}/pathaway-geo.loc
+compare ${REFERENCE}/pathaway-geo.loc ${TMPDIR}/pathaway-geo.loc
+rm -f ${TMPDIR}/pathaway*
+gpsbabel -t -i pathaway -f ${REFERENCE}/track/pathaway.pdb -o gpx -F ${TMPDIR}/pathaway.gpx
+compare ${REFERENCE}/track/pathaway.gpx ${TMPDIR}/pathaway.gpx
--- /dev/null
+# PSP (PocketStreets 2002 Pushpin (.PSP)) file format. Use mxf as an
+# intermediate format to avoid binary FP anomalies on compareerent platforms.
+rm -f ${TMPDIR}/psp.mxf ${TMPDIR}/mxf.psp
+gpsbabel -i psp -f ${REFERENCE}/ps.psp -o mxf -F ${TMPDIR}/psp.mxf
+gpsbabel -i geo -f ${REFERENCE}/../geocaching.loc -o mxf -F ${TMPDIR}/mxf.psp
+compare ${TMPDIR}/psp.mxf ${TMPDIR}/mxf.psp
+gpsbabel -i psp -f ${REFERENCE}/ps.psp -o gpx -F ${TMPDIR}/psp1.gpx
+gpsbabel -i psp -f ${REFERENCE}/ps.psp -o psp -F ${TMPDIR}/xxx.psp
+gpsbabel -i psp -f ${TMPDIR}/xxx.psp -o gpx -F ${TMPDIR}/psp2.gpx
+compare ${TMPDIR}/psp1.gpx ${TMPDIR}/psp2.gpx
--- /dev/null
+
+# QuoVadis GPS for PalmOS
+# This test is derived from the Cetus test.
+rm -f ${TMPDIR}/quovadis.pdb ${TMPDIR}/quovadis.gpu ${TMPDIR}/quovadist.gpu
+gpsbabel -i geo -f ${REFERENCE}/../geocaching.loc -o quovadis -F ${TMPDIR}/quovadis.pdb
+gpsbabel -i quovadis -f ${TMPDIR}/quovadis.pdb -o gpsutil -F ${TMPDIR}/quovadis.gpu
+gpsbabel -i quovadis -f ${REFERENCE}/quovadis.pdb -o gpsutil -F ${TMPDIR}/quovadist.gpu
+compare ${TMPDIR}/quovadist.gpu ${TMPDIR}/quovadis.gpu
+compare ${REFERENCE}/quovadis.gpu ${TMPDIR}/quovadis.gpu
+
+++ /dev/null
-
-#
-# Geocaching Database is a binary Palm format that, like the GPX variants
-# has a zillion "equivalent" encodings of any given record set. So we
-# read the reference file, spin it to GPX and back to GCDB and then spin
-# that one to GPX.
-#
-
-gpsbabel -i gcdb -f ${REFERENCE}/GeocachingDB.PDB -o gpx -F ${TMPDIR}/gcdb1.gpx \
- -o gcdb -F ${TMPDIR}/gcdb1.pdb
-gpsbabel -i gpx -f ${TMPDIR}/gcdb1.gpx -o gpx -F ${TMPDIR}/gcdb2.gpx
-compare ${TMPDIR}/gcdb1.gpx ${TMPDIR}/gcdb1.gpx
-
+++ /dev/null
-#
-# Geoniche: No reference file was available, so we created one and just
-# test it against itself.
-#
-rm -f ${TMPDIR}/gn.pdb ${TMPDIR}/1.gpx ${TMPDIR}/2.gpx
-gpsbabel -i geoniche -f ${REFERENCE}/geoniche.pdb -o geoniche -F ${TMPDIR}/gn.pdb
-gpsbabel -i geoniche -f ${REFERENCE}/geoniche.pdb -o gpx -F ${TMPDIR}/1.gpx
-gpsbabel -i geoniche -f ${TMPDIR}/gn.pdb -o gpx -F ${TMPDIR}/2.gpx
-compare ${TMPDIR}/1.gpx ${TMPDIR}/2.gpx
-#
-gpsbabel -i geoniche -f ${REFERENCE}/gn-targets.pdb -o gpx -F ${TMPDIR}/gn-targets.gpx
-compare ${REFERENCE}/gn-targets.gpx ${TMPDIR}/gn-targets.gpx
+++ /dev/null
-
-#
-# GPilotS. A Palm format. Another binary format that
-#
-# rm -f ${TMPDIR/gpilots.l
-#gpsbabel -i easygps -f ${REFERENCE}/gpilots.pdb -o gpx -F ${TMPDIR}/gp.gpx
-gpsbabel -i geo -f ${REFERENCE}/../geocaching.loc -o gpilots -F ${TMPDIR}/blah.pdb
-gpsbabel -i gpilots -f ${TMPDIR}/blah.pdb -o gpx -F ${TMPDIR}/1.gpx
-gpsbabel -i gpilots -f ${REFERENCE}/gpilots.pdb -o gpx -F ${TMPDIR}/2.gpx
-compare ${TMPDIR}/1.gpx ${TMPDIR}/2.gpx
-#gpsbabel -i easygps -f ${REFERENCE}/gpilots.pdb -o gpx -F ${TMPDIR}/gp.gpx
-
+++ /dev/null
-# GPSPilot Tracker for PalmOS
-# This test is eerily similar to the NAV Companion test. In fact, the
-# converted reference file (magnavr.gpu) is identical.
-rm -f ${TMPDIR}/gpspilot.pdb ${TMPDIR}/gpspilot.gpu ${TMPDIR}/gpspil_t.gpu
-gpsbabel -i geo -f ${REFERENCE}/../geocaching.loc -o gpspilot -F ${TMPDIR}/gpspilot.pdb
-gpsbabel -i gpspilot -f ${TMPDIR}/gpspilot.pdb -o gpsutil -F ${TMPDIR}/gpspilot.gpu
-gpsbabel -i gpspilot -f ${REFERENCE}/gpspilot.pdb -o gpsutil -F ${TMPDIR}/gpspil_t.gpu
-compare ${TMPDIR}/gpspil_t.gpu ${TMPDIR}/gpspilot.gpu
-compare ${REFERENCE}/gu.wpt ${TMPDIR}/gpspilot.gpu
+++ /dev/null
-# hsandv
-rm -f ${TMPDIR}/hsandv.exp ${TMPDIR}/1.exp ${TMPDIR}/1.exp ${TMPDIR}/Glad_5.exp
-gpsbabel -i geo -f ${REFERENCE}/../geocaching.loc -o hsandv -F ${TMPDIR}/hsandv.exp
-compare ${TMPDIR}/hsandv.exp ${REFERENCE}
-#the hsandv format is too lossy to do this test :(
-#gpsbabel -i hsandv -f ${TMPDIR}/hsandv.exp -o geo -F ${TMPDIR}/1.exp
-#gpsbabel -i hsandv -f ${REFERENCE}/hsandv.exp -o geo -F ${TMPDIR}/2.exp
-#compare ${TMPDIR}/1.exp ${TMPDIR}/2.exp
-#test conversion from v4 to v5 files
-gpsbabel -i hsandv -f ${REFERENCE}/Glad_4.exp -o hsandv -F ${TMPDIR}/Glad_5.exp
-# FIXME: Can't compare directly because of potential FP rounding.
-# FIXME: compare ${TMPDIR}/Glad_5.exp reference
+++ /dev/null
-#
-# Map&Guide Palm/OS .pdb files (read-only)
-#
-rm -f ${TMPDIR}/mag_pdb-*
-gpsbabel -i mag_pdb -f ${REFERENCE}/route/mag_pdb-sample.pdb -o gpx -F ${TMPDIR}/mag_pdb-sample.gpx
-compare ${REFERENCE}/route/mag_pdb-sample.gpx ${TMPDIR}/mag_pdb-sample.gpx
-
+++ /dev/null
-# Magellan NAV Companion for PalmOS
-# This format is hard to test, because each record and the database itself
-# contains the time of creation, so two otherwise identical files won't
-# compare accurately. In any case, the files are binary so compare wouldn't
-# like them. So, we convert the reference file to gpsutil and the converted
-# file to gpsutil and make sure they're the same, and that they're the same
-# as one converted on a known-working installation. Unfortunately, this does
-# not verify that the appinfo block was written correctly. However, it does
-# successfully test for some endianness errors that might otherwise go
-# unnoticed.
-rm -f ${TMPDIR}/magnav.pdb ${TMPDIR}/magnav.gpu ${TMPDIR}/magnavt.gpu
-gpsbabel -i geo -f ${REFERENCE}/../geocaching.loc -o magnav -F ${TMPDIR}/magnav.pdb
-gpsbabel -i magnav -f ${TMPDIR}/magnav.pdb -o gpsutil -F ${TMPDIR}/magnav.gpu
-gpsbabel -i magnav -f ${REFERENCE}/magnav.pdb -o gpsutil -F ${TMPDIR}/magnavt.gpu
-compare ${TMPDIR}/magnavt.gpu ${TMPDIR}/magnav.gpu
-compare ${REFERENCE}/gu.wpt ${TMPDIR}/magnav.gpu
-
-rm -f ${TMPDIR}/magnav.pdb
-gpsbabel -i geo -f ${REFERENCE}/../geocaching.loc -o magnav -F ${TMPDIR}/magnav.pdb
-bincompare ${TMPDIR}/magnav.pdb ${REFERENCE}/magnav.pdb
-
+++ /dev/null
-#
-# Microsoft AutoRoute 2002 test (read-only)
-#
-gpsbabel -i msroute -f ${REFERENCE}/route/msroute-sample.axe -o gpx -F ${TMPDIR}/msroute-sample.gpx
-compare ${REFERENCE}/route/msroute-sample.gpx ${TMPDIR}/msroute-sample.gpx
-
+++ /dev/null
-#
-# PathAway Palm Database .pdb tests
-#
-rm -f ${TMPDIR}/pathaway*
-gpsbabel -i geo -f ${REFERENCE}/../geocaching.loc -o pathaway,dbname="pathaway-geo" -F ${TMPDIR}/pathaway-geo.pdb
-gpsbabel -i pathaway -f ${TMPDIR}/pathaway-geo.pdb -o geo -F ${TMPDIR}/pathaway-geo.loc
-compare ${REFERENCE}/pathaway-geo.loc ${TMPDIR}/pathaway-geo.loc
-rm -f ${TMPDIR}/pathaway*
-gpsbabel -t -i pathaway -f ${REFERENCE}/track/pathaway.pdb -o gpx -F ${TMPDIR}/pathaway.gpx
-compare ${REFERENCE}/track/pathaway.gpx ${TMPDIR}/pathaway.gpx
+++ /dev/null
-# PSP (PocketStreets 2002 Pushpin (.PSP)) file format. Use mxf as an
-# intermediate format to avoid binary FP anomalies on compareerent platforms.
-rm -f ${TMPDIR}/psp.mxf ${TMPDIR}/mxf.psp
-gpsbabel -i psp -f ${REFERENCE}/ps.psp -o mxf -F ${TMPDIR}/psp.mxf
-gpsbabel -i geo -f ${REFERENCE}/../geocaching.loc -o mxf -F ${TMPDIR}/mxf.psp
-compare ${TMPDIR}/psp.mxf ${TMPDIR}/mxf.psp
-gpsbabel -i psp -f ${REFERENCE}/ps.psp -o gpx -F ${TMPDIR}/psp1.gpx
-gpsbabel -i psp -f ${REFERENCE}/ps.psp -o psp -F ${TMPDIR}/xxx.psp
-gpsbabel -i psp -f ${TMPDIR}/xxx.psp -o gpx -F ${TMPDIR}/psp2.gpx
-compare ${TMPDIR}/psp1.gpx ${TMPDIR}/psp2.gpx
+++ /dev/null
-
-# QuoVadis GPS for PalmOS
-# This test is derived from the Cetus test.
-rm -f ${TMPDIR}/quovadis.pdb ${TMPDIR}/quovadis.gpu ${TMPDIR}/quovadist.gpu
-gpsbabel -i geo -f ${REFERENCE}/../geocaching.loc -o quovadis -F ${TMPDIR}/quovadis.pdb
-gpsbabel -i quovadis -f ${TMPDIR}/quovadis.pdb -o gpsutil -F ${TMPDIR}/quovadis.gpu
-gpsbabel -i quovadis -f ${REFERENCE}/quovadis.pdb -o gpsutil -F ${TMPDIR}/quovadist.gpu
-compare ${TMPDIR}/quovadist.gpu ${TMPDIR}/quovadis.gpu
-compare ${REFERENCE}/quovadis.gpu ${TMPDIR}/quovadis.gpu
-
extern ff_vecs_t bcr_vecs;
extern ff_vecs_t brauniger_iq_vecs;
extern ff_vecs_t cetus_vecs;
-extern ff_vecs_t coastexp_vecs;
extern ff_vecs_t compegps_vecs;
extern ff_vecs_t copilot_vecs;
extern ff_vecs_t coto_vecs;
extern ff_vecs_t magX_fvecs;
extern ff_vecs_t mapsend_vecs;
extern ff_vecs_t mps_vecs;
-extern ff_vecs_t msroute_vecs;
extern ff_vecs_t mtk_vecs;
extern ff_vecs_t mtk_fvecs;
extern ff_vecs_t mtk_m241_vecs;
extern ff_vecs_t pcx_vecs;
extern ff_vecs_t ppdb_vecs;
extern ff_vecs_t psit_vecs; /* MRCB */
-extern ff_vecs_t psp_vecs;
extern ff_vecs_t quovadis_vecs;
extern ff_vecs_t saroute_vecs;
extern ff_vecs_t shape_vecs;
"gpsutil",
NULL
},
- {
- &psp_vecs,
- "psp",
- "MS PocketStreets 2002 Pushpin",
- "psp"
- },
{
&lowranceusr_vecs,
"lowranceusr",
"Lowrance USR version 4",
"usr"
},
-#if PDBFMTS_ENABLED
- {
- &cetus_vecs,
- "cetus",
- "Cetus for Palm/OS",
- "pdb"
- },
- {
- &copilot_vecs,
- "copilot",
- "CoPilot Flight Planner for Palm/OS",
- "pdb"
- },
- {
- &gpspilot_vecs,
- "gpspilot",
- "GPSPilot Tracker for Palm/OS",
- "pdb"
- },
- {
- &magnav_vec,
- "magnav",
- "Magellan NAV Companion for Palm/OS",
- "pdb"
- },
-#endif /* PDBFMTS_ENABLED */
{
&holux_vecs,
"holux",
"TopoMapPro Places File",
"tmpro"
},
-#if PDBFMTS_ENABLED
- {
- &gcdb_vecs,
- "gcdb",
- "GeocachingDB for Palm/OS",
- "pdb"
- },
-#endif
{
&tiger_vecs,
"tiger",
"EasyGPS binary format",
"loc"
},
-#if PDBFMTS_ENABLED
- {
- &quovadis_vecs,
- "quovadis",
- "Quovadis",
- "pdb"
- },
- {
- &gpilots_vecs,
- "gpilots",
- "GpilotS",
- "pdb"
- },
-#endif
{
&saroute_vecs,
"saroute",
"Navicache.com XML",
NULL
},
- {
- &coastexp_vecs,
- "coastexp",
- "CoastalExplorer XML",
- NULL
- },
{ /* MRCB */
&psit_vecs,
"psitrex",
"ESRI shapefile",
"shp"
},
-#endif
-#if PDBFMTS_ENABLED
- {
- &geoniche_vecs,
- "geoniche",
- "GeoNiche .pdb",
- "pdb"
- },
#endif
{
&gpl_vecs,
"HTML Output",
"html"
},
-#if PDBFMTS_ENABLED
- {
- &palmdoc_vecs,
- "palmdoc",
- "PalmDoc Output",
- "pdb"
- },
-#endif
{
&netstumbler_vecs,
"netstumbler",
"NetStumbler Summary File (text)",
NULL
},
- {
- &HsaEndeavourNavigator_vecs,
- "hsandv",
- "HSA Endeavour Navigator export File",
- NULL
- },
{
&igc_vecs,
"igc",
"Map&Guide 'TourExchangeFormat' XML",
"xml"
},
-#if PDBFMTS_ENABLED
- {
- &ppdb_vecs,
- "pathaway",
- "PathAway Database for Palm/OS",
- "pdb"
- },
-#endif
{
&vitosmt_vecs,
"vitosmt",
"Motorrad Routenplaner (Map&Guide) .bcr files",
"bcr"
},
-#if PDBFMTS_ENABLED
- {
- &coto_vecs,
- "coto",
- "cotoGPS for Palm/OS",
- "pdb"
- },
-#endif
{
&ignr_vecs,
"ignrando",
"txt"
},
#endif // CSVFMTS_ENABLED
- {
- &msroute_vecs,
- "msroute",
- "Microsoft AutoRoute 2002 (pin/route reader)",
- "axe"
- },
- {
- &msroute_vecs,
- "msroute",
- "Microsoft Streets and Trips (pin/route reader)" ,
- "est"
- },
{
&cst_vecs,
"cst",
"Navigon Mobile Navigator .rte files",
"rte"
},
-#if PDBFMTS_ENABLED
- {
- &magpdb_vecs,
- "mag_pdb",
- "Map&Guide to Palm/OS exported files (.pdb)",
- "pdb"
- },
-#endif
#if CSVFMTS_ENABLED
{
&compegps_vecs,